Fragment的懒加载

前言

我们在做安卓项目的时候,经常会有一个使用场景:ViewPage与多个Fragment组合使用。 然而,viewpager有着预加载机制:默认一次加载当前页面前后两个页面,即使设置setOffLimit(0)也没有效果。 虽然预加载优化了app的体验效果,但是这样把我们看不到的页面的数据也加载了,降低了性能,浪费初始化资源。这时我们就需要用到 “懒加载”。

Fragment的生命周期

为了方便了解首先看一下Fragment额生命周期。
在这里插入图片描述

实现思路

1.Fragment中有一个叫 setUserVisibleHint(boolean isVisibleToUser) 的方法,此方法会在onCreateView()之前执行,当viewPager中fragment改变可见状态时也会调用,当fragment 从可见到不见,或者从不可见切换到可见,都会调用此方法,使用getUserVisibleHint() 可以返回fragment是否可见状态。

2.但是直接根据 isVisibleToUser 判断就加载数据,可能onCreateView()方法并未执行完毕,此时就会出现NullPointerException空指针异常。所以就需要满足控件初始化完成,用户可见,才能加载数据。

3.添加 isPrepared 参数。在系统调用onActivityCreated时设置为true,这时onCreateView方法已调用完毕(一般我们在这方法里执行findviewbyid等方法),确保 lazyInitData()方法不会报空指针异常。

4.添加 isInitData 参数。确保ViewPager来回切换时BaseFragment的initData方法不会被重复调用,lazyInitData在该Fragment的整个生命周期只调用一次,第一次调用 lazyInitData() 方法后马上执行 isInitData= true。

5.getUserVisibleHint()会返回是否可见状态,这是fragment实现懒加载的关键,只有fragment 可见才会调用onLazyLoad() 加载数据。

代码示例

//定义一个懒加载的基类
public abstract class BaseFragment extends Fragment {
    protected View rootView;
    private boolean isInitData = false; /*标志位 判断数据是否初始化*/
    private boolean isPrepareView = false; /*标志位 判断view已经加载完成 避免空指针操作*/

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
       // Log.i("TAG","==onActivityCreated");
        isPrepareView = true;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
       rootView = inflater.inflate(getLayoutInt(), container, false);
      //  Log.i("TAG","==onCreateView");
        return rootView;
    }
//判断fragment是否可见
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        Log.i("TAG","==setUserVisibleHint="+getUserVisibleHint());
        if (!isInitData && isVisibleToUser && isPrepareView) {
            lazyInitData();
        }
    }

    /*懒加载方法*/
    private void lazyInitData() {
        if (!isInitData && isVisibleToUser && isPrepareView) {
            isInitData = true;
            initData();
        }
    }
   //初始化数据,数据加载等等。
    public abstract void initData();
    //加载布局
    public abstract int getLayoutInt();
}

在fragment中的使用

public class MyFragment extends BaseFragment {
    private ListView firstList;
    private MFAdatper mfAdatper;

    @Override
    public void initData() {
    //控件初始化
        firstList = rootView.findViewById(R.id.firstList); 
        
      //自己要做的事情(我这里写了一个方法 用于 下载 图片)
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.qubaobei.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        FoodInterFace face = retrofit.create(FoodInterFace.class);
        HashMap<String,String>map = new HashMap<>();
        map.put("stage_id","1");
        map.put("limit","20");
        map.put("page","1");
        Observable<Food> foodInfo = face.getFoodInfo(map);
        foodInfo.
                subscribeOn(Schedulers.io()).
                observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Food>() {
                    @Override
                    public void accept(@NonNull Food food) throws Exception {
                        List<Food.DataBean> data = food.getData();
                        Log.i("TAG","==="+data.size());
                        mfAdatper = new MFAdatper(getContext(),data);
                        firstList.setAdapter(mfAdatper);
                    }
                });
    }
    //===============================================================================================
//加载布局
    @Override
    public int getLayoutInt() {
        return R.layout.list_layout;
    }
}

总结

一个简单的fragment的懒加载 demo就完成了(博主的文笔比较烂,将就看吧)。最后盗张图。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值