问题:
- Activity重建后,为什么 ViewPager里的Fragment多了一倍
- 我的case:自己在ViewPager的adapter里 new的Fragment,系统又 restore 一个 Fragment。
- 然后业务逻辑用 new的Fragment,系统却用restore的Fragment,导致new的Fragment声明周期都没走,之后就会各种异常。
结论先行
- 创建Fragment时,要考虑到Fragment被恢复的case,这时不该 new,而是 恢复状态
- Activity被 销毁 重建后,如果用ViewPager用的 FragmentStatePagerAdapter,系统会重新创建 Fragment 实例
- Activity被销毁时,FragmentManagetImpl 调用saveAllState,将保存Fragment的状态 FragmentManagerState(Parcelable子类 IPC跨进程使用)。
- Activity重建时,会根据 FragmentManagerState ,重新创建Fragment
- 编写Activity时,一定要考虑他会被destroy的情景(比如内存紧张, 这不受你控制)
- 一个内存泄漏就可以引发,当然泄漏多了就OOM,看起来指标不治本
- 怎样模拟Activity被销毁?可以去开发者设置里,勾选 不保存活动 (我没试过,之后试过再确认)
Parcelable saveAllState() {
FragmentManagerState fms = new FragmentManagerState();
fms.mActive = active;
fms.mAdded = added;
fms.mBackStack = backStack;
怎么创建Fragment
在创建前先判断FragmentManager中是否已该Activity
adapter = new FragmentStatePagerAdapter(getChildFragmentManager());
if (getFragmentManager().getFragments() != null) {
adapter.initData(getFragmentManager().getFragments());
} else {
adapter.initData();
}
如果不用ViewPager。Fragment的创建、恢复
private MainFragment mainFragment;
private SecondaryFragment secondaryFragment;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mainFragment = (MainFragment) fm.getFragment(savedInstanceState, MainFragment.TAG);
secondaryFragment = (SecondaryFragment) fm.getFragment(savedInstanceState, SecondaryFragment.TAG);
}
if (mainFragment == null) {
mainFragment = new MainFragment();
}
if(secondaryFragment == null){
secondaryFragment = new SecondaryFragment()
}
// ViewPager 的相关操作
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mainFragment.isAdded()) {
fm.putFragment(outState, MainFragment.TAG, mainFragment);
}
if (secondaryFragment.isAdded()) {
fm.putFragment(outState, SecondaryFragment.TAG, secondaryFragment);
}
}
FragmentPagerAdapter 与 FragmentStatePagerAdapter
- 看这个文章
- FragmentPagerAdapter 是将Fragment保存到 FragmentManager里,进行复用
- 适合静态的、少界面的ViewPager,加载Fragment过多,会增加内存消耗
- FragmentStatePagerAdapter 是通过对 FragmentManagerState 来实现状态的复用(Fragment会被新创建,但状态一致)
- 默认不保存所有的Fragment,而是 前页面1个+当前+后页面1个= 3个页面被缓存
- 前面、后面页面缓存个数通过 ViewPager setOffscreenPageLimit (int limit)设置
- 可以在Activity销毁重建后,回复UI状态