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时

我们可以看到主页BadHomeFragmentsetUserVisibleHint()方法执行了两次!先返回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不可见的时候调用。其实这样说并不完全,应该是从不可见状态到可见状态的时候加载数据,可见状态到不可见状态的时候停止。所以我们得用一个变量记录一下可见状态

可以看到在切换方面,分发的事件已经是正常的了 注意要在onStopcurrentVisibleStatus状态重置!

以上就是我们网上常见的懒加载了,但是会有两个问题

在跳转到其他页面回来时,会怎么样?

并不会怎样,只是回来的时候不会去分发加载数据的事件而已啧 所以我加上这样一段代码,用一个变量去判断,不需要可以不写,但是我想想你跳转了别的页面,回来数据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懒加载的主要内容,如果未能解决你的问题,请参考以下文章

爬取微博的数据时别人用的是FM.view方法传递html标签那么jsoup怎么解析呢

Fragment懒加载

使用PHP+Redis实现微博的用户管理

微博的第三方登录

什么是微博?它有什么作用?怎样使用?

Day773.微博的Redis实践经验 -Redis 核心技术与实战