Fragment生命周期
详细解读每个方法的调用场景
- onAttach方法, Fragment和Activity建立关联的时候调用(获得activity的传递的值)
- onCreateView方法, 为Fragment创建视图(加载布局)时调用(给当前的fragment绘制UI布局,可以使用线程更新UI)
- onActivityCreated方法, 当Activity中的onCreate方法执行完后调用(表示activity执行oncreate方法完成了的时候会调用此方法)
- onDestroyView方法 ,Fragment中的布局被移除时调用(表示fragment销毁相关联的UI布局)
- onDetach方法, Fragment和Activity解除关联的时候调用(脱离activity)
fragment生命周期解析
当一个fragment被创建的时候:
onAttach()
onCreate()
onCreateView()
onActivityCreated()
当这个fragment对用户可见的时候,它会经历以下状态。
onStart()
onResume()
可以理解为从创建到显示(或切换)
当这个fragment进入“后台模式”的时候,它会经历以下状态。
onPause()
onStop()
当这个fragment被销毁了(或者持有它的activity被销毁了):
onPause()
onStop()
onDestroyView()
onDestroy()
onDetach()
就像Activity一样,在以下的状态中,可以使用Bundle对象保存一个fragment的对象。
onCreate()
onCreateView()
onActivityCreated()
其他场景的调用
屏幕灭掉
onPause()
onSaveInstanceState()
onStop()
屏幕解锁
onStart()
onResume()
切换到其他Fragment
onPause()
onStop()
onDestroyView()
切换回本身的Fragment
onCreateView()
onActivityCreated()
onStart()
onResume()
回到桌面
onPause()
onSaveInstanceState()
onStop()
回到应用
onStart()
onResume()
退出应用
onPause()
onStop()
onDestroyView()
onDestroy()
onDetach()
hide和show方式生命周期
现有Fragment1和Fragment2
载入Fragment1,生命周期如下:
- Fragment1 onCreate
- Fragment1 onCreateView
- Fragment1 onStart
- Fragment1 onResume
用add和add切到Fragment2
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.hide(Fragment1);
ft.add(R.id.simple_fragment, Fragment2);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
Fragment1不走任何生命周期,但会调onHiddenChanged方法
1. Fragment2 onCreate
2. Fragment2 onCreateView
3. Fragment2 onStart
4. Fragment2 onResume
用hide和show的方式切换都不会走生命周期
- 使用hide()方法只是隐藏了fragment的view并没有将view从viewtree中删除,随后可用show()方法将view设置为显示。
- 原本需要在onResume以及onPause方法做的事情就可以迁移到onHiddenChanged时进行管理
回到Fragment1,Remove Fragment2
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.remove(Fragment2);
ft.show(Fragment1);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
Fragment1还是不走任何生命周期,调onHiddenChanged方法
Fragment2 onPause
Fragment2 onStop
Fragment2 onDestoryView
Fragment2 onDestory
用这种方法切换,Fragment在隐藏时并不会走onDestoryView,所以显示时也不会走onCreateView,所有View都一直保存在内存中。
replace方式生命周期
Fragment1用replace切到Fragment2
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.simple_fragment, Fragment2);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
这次的Fragment1走生命周期了
Fragment1 onPause
Fragment1 onStop
Fragment1 onDestoryView
Fragment1 onDestory
Fragment2 onCreate
Fragment2 onCreateView
Fragment2 onStart
Fragment2 onResume
Fragment2回到Fragment1
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.simple_fragment, Fragment1);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
Fragment1 onCreate
Fragment1 onCreateView
Fragment1 onStart
Fragment1 onResume
Fragment2 onPause
Fragment2 onStop
Fragment2 onDestoryView
Fragment2 onDestory
Fragment1因为已经被回收,又走onCreate,Fragment2被回收。
这两种方式显然都不满足我的需求,且与生命周期图不同。因为我需要在用户看见/看不见Fragment时register和unregister BroadcastReceiver之类的东西(onHiddenChanged也能实现,但第一次载入显示,以及销毁时不会走onHiddenChanged方法),也不希望用户回到上一个Fragment就重新创建整个Fragment,因为这样消耗资源。
ViewPager里生命周期
根据setUserVisibleHint(boolean isVisibleToUser) 来判断显示隐藏
总结
使用add()加入fragment时将触发onAttach(),使用attach()不会触发onAttach()
使用replace()替换后会将之前的fragment的view从viewtree中删除
触发顺序:
detach()->onPause()->onStop()->onDestroyView()
attach()->onCreateView()->onActivityCreated()->onStart()->onResume()
使用hide()方法只是隐藏了fragment的view并没有将view从viewtree中删除,随后可用show()方法将view设置为显示
而使用detach()会将view从viewtree中删除,和remove()不同,此时fragment的状态依然保持着,在使用attach()时会再次调用onCreateView()来重绘视图,注意使用detach()后fragment.isAdded()方法将返回false,在使用attach()还原fragment后isAdded()会依然返回false(需要再次确认)
执行detach()和replace()后要还原视图的话, 可以在相应的fragment中保持相应的view,并在onCreateView()方法中通过view的parent的removeView()方法将view和parent的关联删除后返回