Fragment懒加载

前言

1.Fragment+ViewPager一块使用的时候,其实懒加载是ViewPager中就有的,看过ViewPager源码的人都知道,ViewPager中有设置默认的懒加载的页数,默认的是1,但是这个1可不是我们通常说的一页,这个1而是左右各一页的意思。

比如:有四个模块分别为:推荐、地图、服务、我的四个模块。
(1)分别为0、1、2、3四个位置,当我们点击“推荐”的时候,按左右各一页原理,要加载“推荐”左边的(没有不加载)和右边的“地图”两个模块。
(2)当我们点击“服务”模块的时候,要加载的是左边一页“地图”和右边一页“我的”两个模块。

其中解决方法:
(1)第一种方式就是把源码里面的Viewpager类里面的代码全部复制出来到自定义的一个类里面把默认值改为0即可。
(2)第二种方式是在Fragment中重写setUserVisibleHint()方法实现Fragment中的懒加载模式。

那么我们就主要讲解一下第二种懒加载的方式:

1.解析

我们在做应用开发的时候,一个Activity里面可能会以Viewpager(或其他容器)与多个Fragment来组合使用,而如果每个Fragment都需要去加载数据,或从本地加载,或从网络加载,那么在这个Activity刚创建的时候就变成需要初始化大量资源。这样的结果,我们当然不会满意。那么,能不能做到当切换到这个Fragment的时候,它才去初始化呢?

2.使用原理

其实答案就在Fragment的setUserVisibleHint这个方法里,当Fragment执行的时候,系统会默认调用该方法,会告诉系统Fragment的UI是否可见。

3.使用方式

所以我们只需要继承Fragment并重写该方法,即可实现在fragment可见时才进行数据加载操作,即Fragment的懒加载。
代码如下:

/*
 * Date: 14-7-17
 * Project: Access-Control-V2
 */
package cn.irains.access_control_v2.common;
import android.support.v4.app.Fragment;
/**
 * Author: msdx (645079761@qq.com)
 * Time: 14-7-17 下午5:46
 */
public abstract class LazyFragment extends Fragment {
    protected boolean isVisible;
    /**
     * 在这里实现Fragment数据的缓加载.
     * @param isVisibleToUser
     */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if(getUserVisibleHint()) {
            isVisible = true;
            onVisible();
        } else {
            isVisible = false;
            onInvisible();
        }
    }
    protected void onVisible(){
        lazyLoad();
    }
    protected abstract void lazyLoad();
    protected void onInvisible(){}
}

4.在LazyFragment,我增加了三个方法,一个是onVisiable,即fragment被设置为可见时调用,一个是onInvisible,即fragment被设置为不可见时调用。另外再写了一个lazyLoad的抽象方法,该方法在onVisible里面调用。你可能会想,为什么不在getUserVisibleHint里面就直接调用呢?

在fragment中,我们还需要创建视图(onCreateView()方法),可能还需要在它不可见时就进行其他小量的初始化操作(比如初始化需要通过AIDL调用的远程服务)等。而setUserVisibleHint是在onCreateView之前调用的,那么在视图未初始化的时候,在lazyLoad当中就使用的话,就会有空指针的异常。而把lazyLoad抽离成一个方法。

然后子类就可以如下代码:

public class OpenResultFragment extends LazyFragment{
    // 标志位,标志已经初始化完成。
    private boolean isPrepared;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d(LOG_TAG, "onCreateView");
        View view = inflater.inflate(R.layout.fragment_open_result, container, false);
        //XXX初始化view的各控件
    isPrepared = true;
        lazyLoad();
        return view;
    }
    @Override
    protected void lazyLoad() {
        if(!isPrepared || !isVisible) {
            return;
        }
        //填充各控件的数据
    }
}

在上面的类当中,我们增加了一个标志位isPrepared,用于标志是否初始化完成。然后在我们所需要的初始化操作完成之后调用,如上面的例子当中,在初始化view之后,设置 isPrepared为true,同时调用lazyLoad()方法。而在lazyLoad()当中,判断isPrepared和isVisible只要有一个不为true就不往下执行。也就是仅当初始化完成,并且可见的时候才继续加载,这样的避免了未初始化完成就使用而带来的问题。

尊重作者:本无转自
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1021/1813.html

如果大家有好的建议和想法,可以留言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疯狂的沙粒

您的鼓励是我创作最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值