关于Activity中的Viewpager中的Fragment的生命周期
2015-01-07 18:07
387 查看
Activity的生命周期是较为经典也最清晰的,在此不表;
Fragment从出现到广泛运用也有一段时间了,其标准生命周期也仅比Activity多出一些流程,如onCreateView();
Activity和Fragment在实际编码中必定是结合出现的,表现为Activity作为容器,装载有一个或若干个Fragment;
装载多个Fragment时,经常使用TabHost和Viewpager作为载体;
在实际编码中发现,Activity和Fragment的混合情况里,其生命周期的交叉可能与预想中有差别;
使用如下方式加载Fragment时:
其onResume和onPause执行过程为:
Activity - onResume
Fragment - onResume
Activity - onPause
Fragment - onPause
Activity和Fragment共同体页面统计中,需要保证线性不交叉,每个onPageStart都有一个onPageEnd配对,
如:onPageStart ->onPageEnd-> onPageStart -> onPageEnd -> onPageStart ->onPageEnd
这样才能保证每个页面统计的正确。
ViewPager装载Fragment一般使用FragmentPagerAdapter或FragmentStatePagerAdapter,同样借助FragmentManager,在adapter的getItem方法中根据position制定显示的fragment
由于Viewpager的缓存特点,Viewpager启动时其第一个Fragment页面及待缓存的页面都将按顺序呢开始他们的正常生命周期,走向onResume,即:
Viewpager所在Activity - onResume
Fragment1 - onResume
Fragment2 - onResume
Fragment3 - onResume
由于这若干个页面的生命周期被同时催化了,影响了我们的单一判断,即无法判断“真正”显示和消失在使用者眼前的页面。
方案1:设置Viewpager的缓存机制,不缓存除当前页以外的页面数据,所见即所得,离开即销毁;
此方案对需求改动较大,且较影响用户体验;
方案2:重载Fragment.onHiddenChanged(boolean hidden)方法,其参数hidden代表当前fragment显隐状态改变时,是否为隐藏状态,可通过check此参数作处理;
此方案局限在于本方法的系统调用时间发生在显隐状态改变时,但第一次显示时此方法并不调用;
方案3:重载Fragment.setUserVisibleHint(boolean isVisibleToUser)方法,其参数isVisibleToUser顾名思义最接近我们的需求,代表页面是否“真正”对使用者显示;
此方案局限在于此方法的第一次系统调用甚至早于Fragment的onCreate方法,故其第一次调用时isVisibleToUser值总为false,影响我们对生命周期顺序的判定;
Fragment1 - isVisibleToUser - false (多余)
Fragment1 - isVisibleToUser - true
Fragment1 - isVisibleToUser - false
Fragment2 - isVisibleToUser - false (多余)
Fragment2 - isVisibleToUser - true
Fragment2 - isVisibleToUser - false
根据对产品需求的理解和用户体验的统一,选择在方案3基础上加以改进;
setUserVisibleHint()方法本身很接近我们的需求,它的局限点我采取了一个侵入式的解决方式:
对onCreate方法结束的一个标记即可解决问题;
切记:此标记的改变请勿放在Fragment的onActivtyCreate方法中,此方法调用滞后于setUserVisibleHint的判断
Viewpager装载Fragment时还有另一个坑,Viewpager的父容器(Activity或Fragment)在显隐状态改变时,如在Activity的onResume和onPause调用时,并不会主动通知Viewpager内的Fragment执行其应用的生命周期,故我们需要再增加手动强制调用两次
在Activity中查询到当前的Fragment,并执行其内方法,需要借助Viewpager,并改写其PagerAdapter;
我采用了此文提到的Second Solution:如何获得ViewPager当前显示的Fragment?
Fragment从出现到广泛运用也有一段时间了,其标准生命周期也仅比Activity多出一些流程,如onCreateView();
Activity和Fragment在实际编码中必定是结合出现的,表现为Activity作为容器,装载有一个或若干个Fragment;
装载多个Fragment时,经常使用TabHost和Viewpager作为载体;
在实际编码中发现,Activity和Fragment的混合情况里,其生命周期的交叉可能与预想中有差别;
使用如下方式加载Fragment时:
getSupportFragmentManager() .beginTransaction() .add(R.id.fragment_container, mFragment, SHARE_PUBLIC_LIST_FRAGMENT_TAG) .commitAllowingStateLoss();
其onResume和onPause执行过程为:
Activity - onResume
Fragment - onResume
Activity - onPause
Fragment - onPause
友盟-页面统计要求
Activity和Fragment共同体页面统计中,需要保证线性不交叉,每个onPageStart都有一个onPageEnd配对,如:onPageStart ->onPageEnd-> onPageStart -> onPageEnd -> onPageStart ->onPageEnd
这样才能保证每个页面统计的正确。
Viewpager中Fragment的生命周期
ViewPager装载Fragment一般使用FragmentPagerAdapter或FragmentStatePagerAdapter,同样借助FragmentManager,在adapter的getItem方法中根据position制定显示的fragment由于Viewpager的缓存特点,Viewpager启动时其第一个Fragment页面及待缓存的页面都将按顺序呢开始他们的正常生命周期,走向onResume,即:
Viewpager所在Activity - onResume
Fragment1 - onResume
Fragment2 - onResume
Fragment3 - onResume
由于这若干个页面的生命周期被同时催化了,影响了我们的单一判断,即无法判断“真正”显示和消失在使用者眼前的页面。
解决方案
方案1:设置Viewpager的缓存机制,不缓存除当前页以外的页面数据,所见即所得,离开即销毁;此方案对需求改动较大,且较影响用户体验;
方案2:重载Fragment.onHiddenChanged(boolean hidden)方法,其参数hidden代表当前fragment显隐状态改变时,是否为隐藏状态,可通过check此参数作处理;
此方案局限在于本方法的系统调用时间发生在显隐状态改变时,但第一次显示时此方法并不调用;
方案3:重载Fragment.setUserVisibleHint(boolean isVisibleToUser)方法,其参数isVisibleToUser顾名思义最接近我们的需求,代表页面是否“真正”对使用者显示;
此方案局限在于此方法的第一次系统调用甚至早于Fragment的onCreate方法,故其第一次调用时isVisibleToUser值总为false,影响我们对生命周期顺序的判定;
Fragment1 - isVisibleToUser - false (多余)
Fragment1 - isVisibleToUser - true
Fragment1 - isVisibleToUser - false
Fragment2 - isVisibleToUser - false (多余)
Fragment2 - isVisibleToUser - true
Fragment2 - isVisibleToUser - false
实际采用的解决方案
根据对产品需求的理解和用户体验的统一,选择在方案3基础上加以改进;setUserVisibleHint()方法本身很接近我们的需求,它的局限点我采取了一个侵入式的解决方式:
protected boolean isCreated = false; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... isCreated = true; } /** * 此方法目前仅适用于标示ViewPager中的Fragment是否真实可见 * For 友盟统计的页面线性不交叉统计需求 */ @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (!isCreated) { return; } if (isVisibleToUser) { umengPageStart(); }else { umengPageEnd(); } }
对onCreate方法结束的一个标记即可解决问题;
切记:此标记的改变请勿放在Fragment的onActivtyCreate方法中,此方法调用滞后于setUserVisibleHint的判断
One more thing
Viewpager装载Fragment时还有另一个坑,Viewpager的父容器(Activity或Fragment)在显隐状态改变时,如在Activity的onResume和onPause调用时,并不会主动通知Viewpager内的Fragment执行其应用的生命周期,故我们需要再增加手动强制调用两次在Activity中查询到当前的Fragment,并执行其内方法,需要借助Viewpager,并改写其PagerAdapter;
我采用了此文提到的Second Solution:如何获得ViewPager当前显示的Fragment?
相关文章推荐
- 关于ViewPager+Fragment中Fragment不销毁/生命周期
- 关于Viewpager中的Fragment的生命周期
- 友盟页面统计 - 关于Viewpager中的Fragment的生命周期
- 关于ViewPager中显示fragment的生命周期调用问题
- 友盟页面统计 - 关于Viewpager中的Fragment的生命周期
- 友盟页面统计 - 关于Viewpager中的Fragment的生命周期
- Android杂谈(15)关于ViewPager里的Fragment的生命周期+懒加载
- 关于ViewPager+Fragment中Fragment不销毁/生命周期
- 关于ViewPager中子Activity生命周期 混乱的问题解决方案
- 关于ViewPager和Fragment配合使用生命周期的问题。
- 关于ViewPager中子Activity生命周期 混乱的问题解决方案
- ViewPager + Fragment 替换 TabActivity
- 使用ViewPager+Fragment来实现带滚动条的多屏滑动-IndicatorFragmentActivity
- 关于ViewPager和Fragment
- 求解viewpager中的fragment切换,怎么返回数据到activity
- 动态设置FragmentActivity+ViewPager+FragmentPagerAdapter结构中的fragment
- 关于Viewpager中的Fragment 滑动时保存状态的问题
- viewpager中fragment的生命周期管理
- android java.lang.NoClassDefFoundError: cn.yw.lib.viewpagerfragment.ViewPagerFragmentActivity
- Android 关于ViewPager结合碎片Fragment的简单使用