首页 > 代码库 > 为Fragment增加入新的生命周期,并实现管理
为Fragment增加入新的生命周期,并实现管理
1. 背景知识
ViewPager+Fragment实现滑动标签页时,默认情况下,Fragment的生命周期是由FragmentPagerAdapter和Activity共同管理的。
(1) Activity维持在onResume状态时,Fragment的生命周期主要由FragmentPagerAdapter进行管理。进行了预加载的Fragment会处于onResume状态(即使没有变成可操作),预加载多少个Fragment,可以通过 ViewPager::setOffscreenPageLimit()函数进行设置。
在切换滑动标签页时,已经预加载的Fragment的生命周期不会被触发改变,仍然是onResume。
(2) 当Activity的生命周期发生变化时,所有已经预加载的Fragment的生命周期与Activity保持一致。
Fragment生命周期与Activity生命周期的关系(主要看onResume和onPause):
onResume执行顺序 :
Activity::onResume() -> Fragment::onResume. (Synchronously)
onPause执行顺序 :
Fragment::onPause -> Activity::onPause. (Synchronously)
2.项目需求
在我们的项目中,因为既需要同时加载多个Fragment, 又需要在Fragment变为可见时做一些事情,不可见时又做一些事情(如切换到该标签页时进行视频播放,退出该标签页时关闭播放),因此,继承Fragment,我们实现自己的MyFragment,在MyFragment中增加了另外两个生命周期: onEnter() (fragment变为可见时回调), onExit()(fragment变为不可见时回调)。这样,我们就可以在onEnter中做开始播放的操作,在onExit中停止播放。
3.解决方案
根据需求中的描述,增加了两个生命周期后,完整的Fragment的生命周期就变为:
onCreate()->onCreateView()->onStart()->onResume()->onEnter()->onExit()->onPause()->onStop()->onDestroyView()->onDestroy().
为了确保生命周期的顺序,需要继承FragmentStatePagerAdapter实现自己的MyFragmentStatePagerAdapter, 重写setPrimaryItem()函数来控制Fragment的生命周期。实现如下:
MyFragmentStatePagerAdapter::setPrimaryItem(ViewGroup container, int position, Object object) {
MyFragment myFragment = (MyFragment)object;
if ((myFragment != NULL) && myFragment.isResumed()) {
if (myFragment != mpCurrentPrimaryItem) {
if (mpCurrentPrimaryItem) {
mpCurrentPrimaryItem.onExit();
mpCurrentPrimaryItem = NULL;
}
if (myFragment) {
myFragment.onEnter();
mpCurrentPrimaryItem = myFragment;
}
}
}
}
- MyFragment::onEnter会在几种情况下被执行:
(1) 当Activity是第一次启动时,进入到onResume, 调用ViewPager::setAdapter()函数第一次给ViewPager设置MyFragmentStatePagerAdapter时, 会回调到setPrimaryItem(), 从而使MyFragment进入onEnter.
(2) 若Activity不是第一次进入onResume, 就不能通过ViewPager::setAdapter使fragment进入onEnter了。这时需要在Activity::onResume中给MyFragment设置一个需要进入onEnter的标记,在MyFragment随后进入onResume时(背景知识有说明),找到MyFragment所在的ViewPager,并获取Adapter, 然后调用setPrimaryItem()使自己进入onEnter.
(3) 切换页面时,由MyFragmentStatePagerAdapter::setPrimaryItem()执行。
- MyFragment::onExit会在两种情况下被执行:
(1) 一种是在Activity执行onPause之后,MyFragmentStatePagerAdapter::setNonePrimaryItem()使MyFragment执行onExit().
MyFragmentStatePagerAdapter::setNonePrimaryItem() {
if (mpCurrentPrimaryItem) {
mpCurrentPrimaryItem.onExit();
mpCurrentPrimaryItem = NULL;
}
}
需要说明的一点是,由于在Activity onPause之前,已经加载的Fragment会先执行onPause, 所以这种情况下不能确保onExit在onPause之前,这时MyFragmnet生命周期为:onResume()->onEnter()->onPause()->onExit()->onStop(). (这点在我们项目中没有影响)
(2) 第二种是在切换页面时,由MyFragmentStatePagerAdapter::setPrimaryItem()实现。
为Fragment增加入新的生命周期,并实现管理