GrowingIO在ViewPager带有Fragment,无法感知生命周期问题

       最近客户反馈几个ViewPager中带Fragment无法感知生命周期的问题。所以对v4包对源码分析一下。现在把结果分享一下。

      很多开发者在开发ViewPager的时候,都会带上预加载功能。常见有FragmentPagerAdapter与FragmentStatePagerAdapter配合ViewPager使用,或者完全自定义实现PagerAdapter。ViewPager的预加载功能会把左右相邻Fragment缓存起来,因此Fragment的生命周期在预加载的时候就会被提前调用,或者没有调用。因此GrowingIO 无法trace目标Fragment。

       所以解决GrowingIO无法track Fragment问题首先了解ViewPager如何配合PagerAdapter对多个Fragment进行管理。先从ViewPager预加载相邻Fragment开始。具体逻辑见如下源码:

GrowingIO在ViewPager带有Fragment,无法感知生命周期问题_第1张图片
预加载左边Fragment代码,位于ViewPager.pupolate()

       上图的逻辑是预加载左边Fragment的代码,位于ViewPager.pupolate()函数中,其中1代码区代码含义是若当前缓存Fragment宽度不合适或位置不对,调用destoryItem销毁目标Fragment。3代码区是若目标Fragment不存在调用addNewItem添加新的Fragment。

        预初始化Fragment逻辑在addNewItem中,源码如下:

GrowingIO在ViewPager带有Fragment,无法感知生命周期问题_第2张图片
添加新预加载Fragment逻辑,位于ViewPager.addNewItem()

       见上图代码,addNewItem通过Adapter.instantiateItem函数初始化Fragment。

       右边相邻的Fragment同理,所以略。

       这就是为什么预加载相邻Fragment时,生命周期会被提前调用对原因。

       下面我们来看,显示当前页是怎样显示的。

预加载左边Fragment代码,位于ViewPager.pupolate()

       当前也的显示与更新是在主要依赖PageAdapter页面。setPrimaryItem是显示当前页面,finishUpdate是页面更新结束。

       由上面对ViewPager源码分析,我们清楚知道ViewPager通过PagerAdapter实现对Fragment对管理。PagerAdapter关键函数有:

instantiateItem: 根据位置,初始化列表对应Fragment。

setPrimaryItem:根据当前位置与当前Fragment对象,显示当前Fragment。

finishUpdate:完成当前显示Fragment页面刷新。

destroyItem:销毁传入对Fragment对象。

       那问题来了,如何识别正在显示对Fragment 与预加载Fragment?

       答案是:Fragment.setUserVisibleHint.

       官方文档对该函数对解释是:告知系统当前Fragment是否对用户显示。

       所以在setPrimaryItem的实现代码中应该调用setUserVisibleHint(true),在instantiateItem的实现代码中,应该调用setUserVisibleHint(false)。v4提供的FragmentStatePagerAdapter、FragmentPageAdapter已经实现该调用,最好直接调用。

       规范PageAdapter的写法后,无缝接入GrowingIO无埋点SDK,帮助你的应用增长吧。


关键词:Android、GrowingIO、ViewPager、Fragment、setUserVisibleHint、预加载。

你可能感兴趣的:(GrowingIO在ViewPager带有Fragment,无法感知生命周期问题)