天天看點

FragmentActivity與Fragment一起使用的緩存問題

1、背景說明

       在界面中,有時候我們會顯示如新浪微網誌底部欄這樣的東西,如下圖所示。這樣的布局結構,我們往往會采用Fragment這種布局去顯示,而不會采用Activity去展示,使用Fragment的好處之一,就是我們複用了他的一些元件,其次,這樣的界面也是基本等價的,是以我們常用元件替換,這樣實作的效果會好于Activity。

      給出一個圖示說明如下:

FragmentActivity與Fragment一起使用的緩存問題

      當然,現在的新浪微網誌的底部欄已經不是這樣的了,這是我從網上截圖過來的一個案例而已。

2、FragmentActivity

      在比較老的Android版本上,我們要實作這樣的一種底部欄的布局,往往會使用TabHost這樣的布局管理器,但是現在已經更新了,我們使用FragmentActivity。

      Fragmentactivity 繼承自activity,用來解決android3.0 之前沒有fragment的api,是以在使用的時候需要導入support包,同時繼承FragmentActivity,這樣在activity中就能嵌入fragment來實作我們想要的布局效果。

      如果我們編譯和運作的版本直接大于3.0,你就不需要導入支援包了,可以直接使用這個控件。

3、FragmentManager

       FragmentManager是和上面的FragmentActivity配合使用的一個元件,界面中的Fragment由FragmentManager管理,負責傳遞Activity的生命周期給所管理的Fragment。

       在Android3.0以上的版本中,可以直接使用get方法擷取FragmentManager對象,即getFragmentManager();在3.0以下的版本中,要使用支援低版本的jar包,可以使用getSupportFragmentManager()這個方法。

4、Fragment

      Fragment是我們界面對象的承受者,可以看做是一個獨立顯示的view對象,不過準确來說他是一個界面控制對象,界面顯示還是通過xml檔案來顯示的。

      在上面,我們提到關于Fragment的作用,是用來對一些功能進行重用的,更準确一點的定義是:Fragment主要的作用是用于分離在Activity中的邏輯代碼, 讓各個獨立的Fragment做自己的事, 互不影響. 便于重用。

       Fragment主要的适用場景,Activity之間的切換不夠流暢,或者是子產品化Activity,友善做局部動畫效果。

       這裡給出一段從網上看到的代碼,适用于某個ViewGroup内動态添加或替代一個Fragment:

KsMainFragment frg = (KsMainFragment) cls.newInstance();
        frg.setArguments(bundle);
        FragmentTransaction ft = getSupportFragmentManager()
                .beginTransaction();
        ft.replace(R.id.fcon_subview, frg);
        mFocusFrage = frg;
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        ft.commit();
           

5、緩存背景

       類似新浪微網誌底部欄的形式,會有許多個條目,但是我們不能每次點選一個選項,該選項的資料就加載一次,這樣在網絡情況不好的時候,使用者體驗很差,即使是網絡很好的情況,也會非常消耗流量,始終是一件不太好的做法。

       我們可以參考新浪微網誌,當我們點選新浪微網誌底部欄目幾個選項的時候,不會出現多次加載的情況(第一次進入首頁,在點選個人中心,然後再次回到首頁,這個時候第二次進入首頁的時候,資料不會再次加載)。如果我們希望更新資料,要麼退出了程式再次進入,或者提供下拉重新整理、按鈕重新整理等這樣的功能,來更新資料。這樣,我們的應用就會比較流暢,體驗度更好,使用者的流量資源消耗得也更少。

       這樣的一種緩存方式也是用的空間換時間,但是對于首頁面上的四五個界面,現在的手機适用綽綽有餘,完全不用擔心會出現OOM異常。

6、示例代碼

       這裡給出一段關于緩存的執行個體代碼,這個,額,是本人公司項目中的一段截取,隻能給出部分代碼,請見諒,但是已經非常完整了,如下:

/**
 * 首頁面
 * 
 * @author ljtyzhr
 * 
 */
public class MainActivity extends FragmentActivity implements OnClickListener {

	private RadioButton radio_btn_home;
	private RadioButton radio_btn_show;
	private RadioButton radio_btn_center;

	private FragmentTransaction transaction = null;
	private List<Fragment> fragments = new ArrayList<Fragment>();
	private FragmentManager fragmentManager = null;

	private FragmentHome fragmentHome = new FragmentHome();
	private FragmentShow fragmentShow = new FragmentShow();
	private FragmentCenter fragmentCenter = new FragmentCenter();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.activity_main);

		// 初始化底部按鈕對象
		initTabView();
	}

	/**
	 * 初始化底部按鈕對象
	 */
	private void initTabView() {
		// 初始化資料
		radio_btn_home = (RadioButton) findViewById(R.id.radio_btn_home);
		radio_btn_show = (RadioButton) findViewById(R.id.radio_btn_show);
		radio_btn_center = (RadioButton) findViewById(R.id.radio_btn_center);

		radio_btn_home.setOnClickListener(this);
		radio_btn_show.setOnClickListener(this);
		radio_btn_center.setOnClickListener(this);

		if (!radio_btn_home.isChecked()) {
			radio_btn_home.setChecked(true);
		}

		fragments.add(fragmentHome);
		fragments.add(fragmentShow);
		fragments.add(fragmentCenter);

		fragmentManager = this.getSupportFragmentManager();
		transaction = fragmentManager.beginTransaction();
		transaction.add(R.id.main_frg_content, fragmentHome);
		transaction.add(R.id.main_frg_content, fragmentShow);
		transaction.add(R.id.main_frg_content, fragmentCenter);
		transaction.show(fragmentHome).hide(fragmentShow).hide(fragmentCenter);
		transaction.commitAllowingStateLoss();
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		// 點選的首頁資料
		case R.id.radio_btn_home:
			switchFragment(0);
			break;
		case R.id.radio_btn_show:
			switchFragment(1);
			break;
		case R.id.radio_btn_center:
			switchFragment(2);
			break;
		default:
			// 預設選中首頁
			switchFragment(0);
			break;
		}
	}

	/**
	 * 更改Fragment對象
	 * 
	 * @param index
	 */
	private void switchFragment(int index) {
		transaction = fragmentManager.beginTransaction();
		transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
		for (int i = 0; i < fragments.size(); i++) {
			if (index == i) {
				transaction.show(fragments.get(index));
			} else {
				transaction.hide(fragments.get(i));
			}
		}
		transaction.commit();
	}

}
           

7、總結

       在上面,我們隻是介紹了怎麼使用FragmentActivity和FragmentManager對Fragment進行管理,以及如何進行緩存處理。我們并沒有介紹如何重新整理,這個下拉重新整理是一個很重要的功能,我們總不能因為使用了這種控件,為使用者節約流量,卻要使用者再次加載才重新整理資料吧。

      這裡推薦使用第三方的下拉重新整理控件,github上有一個pulltorefresh這樣的第三方的庫,大家可以下載下傳看看,使用一下。

      如果掌握上面的緩存處理以及下拉重新整理,其實新浪微網誌的首頁也就基本出來了。哈哈

繼續閱讀