Fragment的优化问题

Android中Fragment经常用到,关于优化问题有必要啰嗦几句。

切换Fragment有两种常用的方法:

1、用Replace替换Fragment;

2、使用add、hide和show方法实现Fragment的切换。 一、使用Replace方法,如下:

1
2
3
4
5
public void replaceFragment(Fragment fragment) {
mFragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment)
.commit();
}

这种方法每次切换,Fragment都会重新实例化,重新走一遍其生命周期。这样findViewById就会执行多次,很浪费性能。如果其中还有网络拉取数据,会很浪费用户的流量,不推荐。

所以,就有了第二种方法。

二、使用add、hide和show实现切换,如下:

1
2
3
4
5
6
7
8
9
10
public void replaceFragment(Fragment from, Fragment to) {
if(from == null || to == null){
return;
}
if (!to.isAdded()) {//判断是否被添加,若没有添加,则添加
mFragmentManager.beginTransaction().hide(from).add(R.id.content_frame, to).commit();
} else {
mFragmentManager.beginTransaction().hide(from).show(to).commit();
}
}

这种方式避免了重复创建Fragment实例的问题,但是又会出现另一个问题——重叠。

导致重叠的原因可能是:

系统回收了Fragment1的引用,但是Fragment1的实例还在内存中,当再次返回时切换到Fragment2,但是找不到Fragment1的引用而无法隐藏,导致与正要show的Fragment2重叠。切回Fragment1,系统会重复创建Fragment1实例。

解决办法:

1、为每个Fragment添加一个TAG,再通过TAG分别取显示隐藏对应的Fragment。

1
2
3
4
5
Fragment f1 = mFragmentManager.beginTransaction().add(R.id.content_frame, fragment, "TAG1");
Fragment f2 = mFragmentManager.beginTransaction().add(R.id.content_frame, fragment, "TAG2");
//再分别hide或show对应的Fragment
//...

2、离开的Fragment未被销毁,只是调用了onDestoryView,当重新恢复时调用onCreateView。在Fragment的onSaveInstanceState中保存实例变量状态,在onActivityCreated中恢复实例变量状态,详见The Real Best Practices to Save/Restore Activity's and Fragment's state

原文参考: - 让多个Fragment 切换时不重新实例化The Real - Best Practices to Save/Restore Activity's and Fragment's state