首页 > 代码库 > FragmentActivity与Fragment一起使用的缓存问题

FragmentActivity与Fragment一起使用的缓存问题

1、背景说明

       在界面中,有时候我们会显示如新浪微博底部栏这样的东西,如下图所示。这样的布局结构,我们往往会采用Fragment这种布局去显示,而不会采用Activity去展示,使用Fragment的好处之一,就是我们复用了他的一些组件,其次,这样的界面也是基本等价的,所以我们常用组件替换,这样实现的效果会好于Activity。

      给出一个图示说明如下:


      当然,现在的新浪微博的底部栏已经不是这样的了,这是我从网上截图过来的一个案例而已。


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这样的第三方的库,大家可以下载看看,使用一下。

      如果掌握上面的缓存处理以及下拉刷新,其实新浪微博的首页也就基本出来了。哈哈

FragmentActivity与Fragment一起使用的缓存问题