ViewPager切换防止Fragment销毁以及取消Fragment的预加载

存在的问题
1. 默认情况下,ViewPager会自动预加载
2. 切换过程中会销毁fragment视图

下面的图说明情况

Paste_Image.png

如图,在Activity中使用ViewPager嵌套三个Fragment,当fragment1出现的时候,此时会预加载fragment2,滑动到fragment2会预加载fragment3,但是滑动到fragment3,此时会调用fragment1的destroyview方法,销毁视图。当重新滑动到fragment1才会重新调用fragment1的oncreateview方法。注意此时并不会销毁实例,不会调用ondestroy方法。

这样就存在两个问题

1、pagerview频繁切换,导致fragment1.fragment3在频繁的调用destroyview和oncreateview方法,重新创建视图。这样也浪费了大量的资源,用户体验不佳,虽然内存消耗比较低

2、因为切换到fragment1的时候,同时预加载了fragment2,如果此时fragment2也有大量的耗时网络请求要做,如果应用对启动反应速度比较敏感,所以此时做了多余的工作。或者说fragment2也会显示加载进度,显然不符合我们的预期,能否把这些耗时的工作延迟加载,也是个问题

防止频繁的销毁视图的解决方案

1、setOffscreenPageLimit(2)
2、或者重写PagerAdaper的destroyItem方法为空即可
笔者此处使用的是方案2

public class MyViewPagerAdapter extends FragmentPagerAdapter {

        ...

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            //如果注释这行,那么不管怎么切换,page都不会被销毁
            //super.destroyItem(container, position, object);
        }
    }

取消预加载解决方案

介绍两个方法void setUserVisibleHint(boolean isVisibleToUser)、boolean getUserVisibleHint(),它们分别用作设置/获得Fragment可见状态,我们可以重写Fragment在其中做判断。

第一步:重写Fragment

public abstract class BaseFragment extends Fragment{


    /** Fragment当前状态是否可见 */
    protected boolean isVisible;

    public void onCreate(android.os.Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);

        if(getUserVisibleHint()) {
            isVisible = true;
            onVisible();
        } else {
            isVisible = false;
            onInvisible();
        }
    }

    /**
     * 可见
     */
    protected void onVisible() {
        lazyLoad();
    }

    /**
     * 不可见
     */
    protected void onInvisible() {
    }

    /**
     * 延迟加载
     * 子类必须重写此方法
     */
    protected abstract void lazyLoad();
}

第二步:继承BaseFragment

1、声明二个重要的变量

private boolean mHasLoadedOnce = false;
private boolean isPrepared = false;

2、onCreateView中进行控件初始化,初始化完成后加载数据

 @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_layuot2, null);
        Dbug.d("","Fragment2==onCreateView");
        initData();
        isPrepared = true;
        lazyLoad();
        return view;
    }

此处为什么要用isPrepared呢,因为lazyLoad();方法调用的时候控件可能没初始化完成,会报空指针错误。

3、lazyLoad中判断是否是首次加载和初始化完成

 @Override
    protected void lazyLoad() {
        if (mHasLoadedOnce || !isPrepared)
            return;
        mHasLoadedOnce = true;
    }

4、onDestroyView中变量重置

 @Override
    public void onDestroyView() {
        super.onDestroyView();
        Dbug.d("","Fragment2==onDestroyView");
        mHasLoadedOnce = false;
        isPrepared = false;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序员学园

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值