Android模仿微博的LazyFragment懒加载

前言 本文会从头开始一步一步带你去写一个LazyFragment,根据写的过程中一步一步记录,你也可以自己试一试,跟着一起写写。最后也根据遇到的问题去完善了,网上搜的都是不完善的,还是自己写一个吧!
懒加载是在加载啥?
这个问题显得很愚蠢。但是想一下,懒加载到底是加载数据和视图,还是数据呢??(一开始我也想过这个问题。。。)当然是数据啦,你怎么能阻止视图的加载呢!你是无法阻止Fragment的生命周期函数的执行的,所以只能让当前显示的Fragment加载数据,不显示不加载数据
怎么能知道当前页面是显示的这个Fragment呢?
在源码中有两个方法可以使用

在viewpager和fragment模式使用的 public void setUserVisibleHint(boolean isVisibleToUser) {}


在add+show+hide模式使用 public void onHiddenChanged(boolean hidden) {}

那么就先简单的试试看这两个方法好了 我写了一个Viewpager+Fragment模式的,缓存数量offscreenPageLimit为1
当打开app时
我们可以看到主页BadHomeFragmentsetUserVisibleHint()方法执行了两次!先返回false不可见,再返回true可见。而且不管在哪个Fragment中setUserVisibleHint()都跑得比生命周期快Android模仿微博的LazyFragment懒加载
文章图片

当切换到第二个Fragment
Android模仿微博的LazyFragment懒加载
文章图片

切回去主页Fragment
当已经跑过生命流程的Fragment再次显示时,只会走setUserVisibleHint()(先忽略onHiddenChange方法)
Android模仿微博的LazyFragment懒加载
文章图片

这样的话,我们大概可以想到,我根据setUserVisibleHint()的可见状态去加载数据不就完事了吗?
所以我们先这样写
Android模仿微博的LazyFragment懒加载
文章图片

在子Fragment中的loadData中调用接口获取数据,然后给控件赋值
Android模仿微博的LazyFragment懒加载
文章图片

结果就是!报错!!说你的控件为null,我都可见了为啥为null呢。因为在进入app时setUserVisibleHint在生命周期前面,Fragment都没有加载布局,当然为null啦
Android模仿微博的LazyFragment懒加载
文章图片

那我加个变量判断一下布局有没有加载好不就行了?
Android模仿微博的LazyFragment懒加载
文章图片

结果呢?主页Fragment没有执行onLoadData方法,点击TwoFragment却执行了,为什么呢,因为setUserVisibleHint更早啊,而TwoFragment已经初始化过了,点击过去的时候才能正常加载数据。
Android模仿微博的LazyFragment懒加载
文章图片

所以我们必须在生命周期中再分发一次加载数据的事件,把加载数据提成一个方法Android模仿微博的LazyFragment懒加载
文章图片

再来看看从开启app到点击到第三个Fragment的日志,大家都正常的加载了数据,好像还挺正常的Android模仿微博的LazyFragment懒加载
文章图片

那再试试从第一个页面跳转到最后一个页面吧,会发现中间有些页面莫名的就调用了StopLoadData函数???这显然有问题的,看来不能只是简单的用可见状态来分发了 Android模仿微博的LazyFragment懒加载
文章图片

我们在好好想一下,LoadData是Fragment可见的时候调用, StopLoadData是Fragment不可见的时候调用。其实这样说并不完全,应该是从不可见状态到可见状态的时候加载数据,可见状态到不可见状态的时候停止。所以我们得用一个变量记录一下可见状态
Android模仿微博的LazyFragment懒加载
文章图片

可以看到在切换方面,分发的事件已经是正常的了 注意要在onStop把`currentVisibleStatus状态重置!
Android模仿微博的LazyFragment懒加载
文章图片

以上就是我们网上常见的懒加载了,但是会有两个问题
在跳转到其他页面回来时,会怎么样?
并不会怎样,只是回来的时候不会去分发加载数据的事件而已啧 所以我加上这样一段代码,用一个变量去判断,不需要可以不写,但是我想想你跳转了别的页面,回来数据Fragment数据应该会变,所以分发一下
Android模仿微博的LazyFragment懒加载
文章图片

在子Fragment中又有一个viewpager+Fragment又会怎么样?
这里去除掉了其他log,为了看起来清楚点
【Android模仿微博的LazyFragment懒加载】我给TowFragment加了一个viewpager,里面有TowFragment1和2
进入App可以看到,爹都还没显示,儿子先加载了数据?Android模仿微博的LazyFragment懒加载
文章图片

而且在之后的切换底部Tab,TowFragment里面的两个儿子都无动于衷,只有刚打开App时加载了,连停止加载的方法都没调用到,根本就没有事件分发到儿子那里去 Android模仿微博的LazyFragment懒加载
文章图片

所以我们必须要再做一些根据父亲和儿子的状态再做一些判断 先解决第一个问题,父Fragment还没显示,子Fragment就加载了数据。这个问题很简单,我们只需要在分发加载数据的事件时,判断一下是否有父Fragment,且是否可见。就可以了
根据Fragment源码中的这个方法,可以解决上面的问题Android模仿微博的LazyFragment懒加载
文章图片

比如,父Fragment不可见时直接退出方法,不准分发 Android模仿微博的LazyFragment懒加载
文章图片

但是还有一个问题存在,就是不管怎么切换,子Fragment都不会分发加载或停止加载数据的事件。这是为啥??
从一开始我们可以看到,在进入HomeFragment时,子Fragment也会分别调用两次setUserVisibleHint方法,在进入前就把自己的可见状态置为true。到底后面的分发事件无效了。
所以我决定在进入他的父Fragment时,再去调用一次分发事件,真正的加载子Fragment的数据,比如Android模仿微博的LazyFragment懒加载
文章图片

可以看见切换都是正常的 Android模仿微博的LazyFragment懒加载
文章图片

最后 今天的文章就到这里,感谢您的阅读,有问题可以在评论区留言探讨,期待与大家共同进步。喜欢的话不要忘了三连。大家的支持和认可,是我分享的最大动力。

    推荐阅读