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

来源:互联网 发布:js this对象 编辑:程序博客网 时间:2024/05/22 13:26

存在的问题
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;    }
0 0
原创粉丝点击