Fragment懒加载实现以及遇到的坑

本文深入探讨了在Android开发中使用ViewPager与Fragment组合时,如何通过懒加载提高应用性能。详细介绍了懒加载的实现原理,包括Fragment的setUserVisibleHint()方法的应用,以及如何通过布尔标志位判断数据是否加载和视图是否准备就绪。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近做项目用到了懒加载,记录一下吧

ViewPager+Fragment的组合,用了无数遍了吧,尤其在有很多个Fragment的情况下,我们没必要把每一个Fragment都加载出来。虽然预加载可以提升一些体验,但是把我们没有看到的页面数据也加载了,大大降低了性能,浪费初始化资源。

什么是懒加载呢,说白了就是页面可见时再去加载

实现原理:

  • Fragment的setUserVisibleHint()方法,此方法在onCreateView()之前执行。
  • getUserVisibleHint()方法可以返回fragment是否是可见状态
  • Fragment中定义两个boolean变量,分别标记是否加载过和View是否准备完毕。

关键代码:


public class LazyLoadFragment extends BaseFragment {

  
    /** 懒加载,是否已经加载过数据, 此标志位只变化一次 */
    private boolean isLazyLoaded;
    /** 页面View是否准备完毕 */
    private boolean isViewPrepared;


    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        isViewPrepared = true;
        onLazyLoad();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        isViewPrepared = false;
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        onLazyLoad();
    }
    
    /**
     *此方法只会执行一次
     */
    private void onLazyLoad() {
        // 同时满足这三个条件,才会去加载数据
        if (getUserVisibleHint() && isViewPrepared && !isLazyLoaded) {
            isLazyLoaded = true;
            // todo 加载数据
        }
    }

}

这里有两个问题:

1、为什么onLazyLoad()会在两个地方执行?

我们知道ViewPager默认显示第一页,然后不设置setOffscreenPageLimit()的情况下,会默认加载下一页,而setUserVisibleHint()是在onCreateView()之前执行的。

假设有5个Fragment

  • 刚开始Fragment1和Fragment2先加载,因为setUserVisibleHint()的时候Fragment1的View还没有初始化完毕,所以Fragment1最终会执行onActivityCreated()方法中的onLazyLoad()去加载数据。而Fragment2并不可见,所以Fragment2并没有加载数据。
  • 然后我们再切换到Fragment2,Fragment3会执行初始化,因为Fragment2在刚才已经初始化了,View已经初始化完毕,isViewPrepared标志位变化为true,Fragment2会直接执行setUserVisibleHint()中的onLazyLoad()方法去加载数据。
  • 然后我们直接切换到fragment5,因为之前fragment5并没有初始化,所以它也会执行onActivityCreated()方法中的onLazyLoad()去加载数据。

在onActivityCreated()中执行onLazyLoad():在初始化第一个Fragment或者直接切换到没有初始化过的Fragment时

在setUserVisibleHint()中执行onLazyLoad():在切换到相邻的Fragment时,此Fragment之前已经初始化过View

2、onDestroyView()中为什么要把isViewPrepared置为false?

这个问题我切身遇到过,还是5个Fragment

刚开始初始化Fragment1和Fragment2,直接切换到Fragment5,然后再切换到Fragment2,直接程序崩溃

日志搞一下:

在切换到Fragment5之后,其实ViewPager就把Fragment1和Fragment2的View销毁了,执行了onDestroyView()方法,但是此时Fragment2的isViewCreated=true,所以在切换过去时执行了setUserVisibleHint()方法中的onLazyLoad(),而此时View都是null,如果加载数据在网络请求之前有直接对View操作的代码那就直接程序崩溃了。

总结

懒加载其实也没什么,理解了原理就觉得很容易了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值