Android 懒加载优化
1.什么是懒加载
1.1 什么是预加载
- ViewPager+Fragment的搭配在日常开发中也比较常见,可用于切换展示不同类别的页面,我们日常所见的咨询、购物、金融、社交等类型的APP都有机会用到这种控件组合
- ViewPager控件有个特有的预加载机制,即默认情况下当前页面左右两侧的1个页面会被加载,以方便用户滑动切换到相邻的界面时,可以更加顺畅的显示出来。
- 通过ViewPager的setOffscreenPageLimit(int limit)可以设置预加载页面数量,当前页面相邻的limit个页面会被预加载进内存
1.2 懒加载介绍
- 懒加载,其实也就是延迟加载,就是等到该页面的UI展示给用户时,再加载该页面的数据(从网络、数据库等),而不是依靠ViewPager预加载机制提前加载两三个,甚至更多页面的数据。这样可以提高所属Activity的初始化速度,也可以为用户节省流量.而这种懒加载的方式也已经/正在被诸多APP所采用。
- 但是通过ViewPager方法setOffscreenPageLimit(int limit)的源码可以发现,ViewPager通过一定的逻辑判断来确保至少会预加载左右两侧相邻的1个页面,也就是说无法通过简单的配置做到懒加载的效果。
1.3 懒加载概括
- 当页面可见的时候,才加载当前页面。
- 没有打开的页面,就不会预加载。
- 说白了,懒加载就是可见的时候才去请求数据。
2.实际应用中有哪些懒加载案例
- 1.1 ViewPager+Fragment的搭配使用懒加载
- 1.2 H5网页使用懒加载
3.ViewPager中setOffscreenPageLimit(int limit)相关源码
- 3.1 源码如下所示
1 | //默认的缓存页面数量(常量) |
- 3.2 分析源码可知
- ViewPager通过一定的逻辑判断来确保至少会预加载左右两侧相邻的1个页面,也就是说无法通过简单的配置做到懒加载的效果。
4.关于ViewPager与Fragment懒加载
4.1 遇到的问题
- 在使用viewpager(或其他容器)与多个Fragment来组合使用,ViewPager 会默认一次加载当前页面前后隔一个页面,即使设置setofflimit(0)也无效果,也会预加载。这样把我们看不到的页面的数据也加载了,大大降低了性能,浪费初始化资源。然而我们就采用懒加载技术,只让用户看到的页面才会加载他的数据,大大提高效率。
4.2 主要的思路做法
- 主要的方法是Fragment中的setUserVisibleHint(),此方法会在onCreateView()之前执行,当viewPager中fragment改变可见状态时也会调用,当fragment 从可见到不见,或者从不可见切换到可见,都会调用此方法,使用getUserVisibleHint() 可以返回fragment是否可见状态。
- 在BaseMVPLazyFragment中需要在onActivityCreated()及setUserVisibleHint()方法中都调了一次lazyLoad() 方法。如果仅仅在setUserVisibleHint()调用lazyLoad(),当默认首页首先加载时会导致viewPager的首页第一次展示时没有数据显示,切换一下才会有数据。因为首页fragment的setUserVisible()在onActivityCreated() 之前调用,此时isPrepared为false 导致首页fragment 没能调用onLazyLoad()方法加载数据。
4.3 代码案例展示
1 | public abstract class BaseMVPLazyFragment<T extends IBasePresenter> extends BaseMVPFragment<T> { |
4.4 onLazyLoad()加载数据条件
- getUserVisibleHint()会返回是否可见状态,这是fragment实现懒加载的关键,只有fragment 可见才会调用onLazyLoad() 加载数据。
- isPrepared参数在系统调用onActivityCreated时设置为true,这时onCreateView方法已调用完毕(一般我们在这方法里执行findviewbyid等方法),确保 onLazyLoad()方法不会报空指针异常。
- isLazyLoaded确保ViewPager来回切换时BaseFragment的initData方法不会被重复调用,onLazyLoad在该Fragment的整个生命周期只调用一次,第一次调用onLazyLoad()方法后马上执行 isLazyLoaded = true。
- 然后再继承这个BaseMVPLazyFragment实现onLazyLoad() 方法就行。他会自动控制当fragment 展现出来时,才会加载数据
4.5 Fragment的方法setUserVisibleHint
- 源码如下所示
- 通过此方法来设置Fragment的UI对用户是否可见,当该页面对用户可见/不可见时,系统都会回调此方法。
- 我们可以重写此方法,然后根据回调的isVisibleToUser参数来进行相关的逻辑判断,以达到懒加载的效果,比如如果isVisibleToUser==true的话表示当前Fragment对用户可见,此时再去加载页面数据。
5.懒加载Fragment为什么要继承BaseFragment
- 5.1 继承BaseFragment好处
- 这个BaseFragment就是最基础的基类了,里面进行一些最底层的设置,定义抽象函数:比如布局文件的绑定,初始化视图控件,初始化数据,初始化Toolbar
- 所以这个懒加载LazyLoadFragment基本上是隔离开了。耦合度相当低,基本都可以这样使用吧。
- 还有一点,有些Fragment不需要懒加载,那么可以直接继承BaseFragment类;需要懒加载的直接继承BaseMVPLazyFragment类