Android模仿微博的LazyFragment懒加载
Posted 沈页
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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时
我们可以看到主页BadHomeFragment
的setUserVisibleHint()方法
执行了两次
!先返回false不可见,再返回true可见。而且不管在哪个Fragment中setUserVisibleHint()
都跑得比生命周期快
当切换到第二个Fragment
切回去主页Fragment
当已经跑过生命流程的Fragment再次显示时,只会走setUserVisibleHint()
(先忽略onHiddenChange方法)
这样的话,我们大概可以想到,我根据setUserVisibleHint()的可见状态
去加载数据不就完事了吗?
所以我们先这样写
在子Fragment中的loadData中调用接口获取数据,然后给控件赋值
结果就是!报错!!说你的控件为null,我都可见了为啥为null呢。因为在进入app时setUserVisibleHint
在生命周期前面,Fragment都没有加载布局,当然为null啦
那我加个变量判断一下布局有没有加载好不就行了?
结果呢?主页Fragment没有执行onLoadData
方法,点击TwoFragment
却执行了,为什么呢,因为setUserVisibleHint
更早啊,而TwoFragment
已经初始化过了,点击过去的时候才能正常加载数据。
所以我们必须在生命周期中再分发一次加载数据的事件,把加载数据提成一个方法
再来看看从开启app到点击到第三个Fragment的日志,大家都正常的加载了数据,好像还挺正常的
那再试试从第一个页面跳转到最后一个页面吧,会发现中间有些页面莫名的就调用了StopLoadData
函数???这显然有问题的,看来不能只是简单的用可见状态来分发了
我们在好好想一下,LoadData
是Fragment可见的时候调用, StopLoadData
是Fragment不可见的时候调用。其实这样说并不完全,应该是从不可见状态到可见状态的时候
加载数据,可见状态到不可见状态的时候
停止。所以我们得用一个变量记录一下可见状态
可以看到在切换方面,分发的事件已经是正常的了 注意要在onStop
把currentVisibleStatus状态重置!
以上就是我们网上常见的懒加载了,但是会有两个问题
在跳转到其他页面回来时,会怎么样?
并不会怎样,只是回来的时候不会去分发加载数据的事件而已啧 所以我加上这样一段代码,用一个变量去判断,不需要可以不写,但是我想想你跳转了别的页面,回来数据Fragment数据应该会变,所以分发一下
在子Fragment中又有一个viewpager+Fragment又会怎么样?
这里去除掉了其他log,为了看起来清楚点
我给TowFragment加了一个viewpager,里面有TowFragment1和2
进入App可以看到,爹都还没显示,儿子先加载了数据?
而且在之后的切换底部Tab,TowFragment里面的两个儿子都无动于衷,只有刚打开App时加载了,连停止加载的方法都没调用到,根本就没有事件分发到儿子那里去
所以我们必须要再做一些根据父亲和儿子的状态再做一些判断 先解决第一个问题,父Fragment还没显示,子Fragment就加载了数据。这个问题很简单,我们只需要在分发加载数据的事件时,判断一下是否有父Fragment,且是否可见。
就可以了
根据Fragment源码中的这个方法,可以解决上面的问题
比如,父Fragment不可见时直接退出方法,不准分发
但是还有一个问题存在,就是不管怎么切换,子Fragment都不会分发加载或停止加载数据的事件。这是为啥??
从一开始我们可以看到,在进入HomeFragment时,子Fragment也会分别调用两次setUserVisibleHint方法
,在进入前就把自己的可见状态置为true。到底后面的分发事件无效了。
所以我决定在进入他的父Fragment时,再去调用一次分发事件,真正的加载子Fragment的数据,比如
可以看见切换都是正常的
最后到这里这个懒加载的写作思路就这样结束了~ 接下来就是加上SmartRefresh控件去模仿微博的加载模式了(当然只能简陋的模仿),有空会补上的!
以上是关于Android模仿微博的LazyFragment懒加载的主要内容,如果未能解决你的问题,请参考以下文章