viewPage+fragment 生命周期的研究,以及懒加载的实现

ViewPage+Fragment 生命周期的研究,以及懒加载的实现

一、ViewPage + Fragment 使用起来很方便。代码量很少。


参考:这个博客

创建三个fragment,添加进去。

二、查看正常情况下的,生命周期。

贴出其中一个fragment的代码,其他都一样(BaseFragmnt暂时是空的,后面用来实现懒加载)。

public class FirstFragment extends BaseFragment{
    
    

    private static final String TAG = "FirstFragment";
    
    
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
    
    
        Log.d(TAG, "onCreateView: ");
        return inflater.inflate(R.layout.fragment_first,container,false);
    }


    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    
    
        super.onActivityCreated(savedInstanceState);
        Log.d(TAG, "onActivityCreated: ");
    }


    @Override
    public void onAttach(Context context) {
    
    
        super.onAttach(context);
        Log.d(TAG, "onAttach: ");
    }

    @Override
    public void onAttachFragment(Fragment childFragment) {
    
    
        super.onAttachFragment(childFragment);
        Log.d(TAG, "onAttachFragment: ");
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
    
    
        super.setUserVisibleHint(isVisibleToUser);
        Log.d(TAG, "setUserVisibleHint: " + isVisibleToUser);
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate: ");
    }

    @Override
    public void onStop() {
    
    
        super.onStop();
        Log.d(TAG, "onStop: ");
    }

    @Override
    public void onDestroy() {
    
    
        super.onDestroy();
        Log.d(TAG, "onDestroy: ");
    }

    @Override
    public void onPause() {
    
    
        super.onPause();
        Log.d(TAG, "onPause: ");
    }

    @Override
    public void onResume() {
    
    
        super.onResume();
        Log.d(TAG, "onResume: ");
    }

    @Override
    public void onDestroyView() {
    
    
        super.onDestroyView();
        Log.d(TAG, "onDestroyView: ");
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
    
    
        super.onHiddenChanged(hidden);
        Log.d(TAG, "onHiddenChanged: " + hidden);

    }

    @Override
    public void onStart() {
    
    
        super.onStart();
        Log.d(TAG, "onStart: ");
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    
    
        super.onViewCreated(view, savedInstanceState);
        Log.d(TAG, "onViewCreated: ");
    }
}

(FirstFragment、SecondFragmet、ThreeFragment按顺序添加)
这是点开应用后,所有Fragment的生命周期日志。

在这里插入图片描述

很明显,大局来看,只加载了前两个Fragment。
具体的方法上最开始 先走setUserVisibleHint方法 都返回的 false(还没有出现在屏幕上),之后第一个Fragment 的 setUserVisibleHint返回true了。然后按顺序第一个fragment的onAttach -> onCreate,第二个fragment的onAttach -> onCreate,第一个fragment的onCreateView -> onViewCreated -> onActivityCreated -> onStart -> onResume。第二个fragment同样。清晰明了。
viewpage与fragment配合,默认是开启预加载的。默认允许两个fragment同时运行,当滑动到第二个fragment时,会自动预加载第三个fragment。
mainViewPage.setOffscreenPageLimit(2);//通过这个修改

当滑动到第三个页面时,则会将第一个页面被销毁了。(接下来我们看运行是生命周期)

我们滑动到第二个fragment页面。

在这里插入图片描述

还是一样,都是先进入 setUserVisibleHint 方法,根据当前页面显示的情况返回true或者false。然后就是第三个fragmen开始初始化,创建。

当我们再滑到第三个页面时

在这里插入图片描述

第一个fragment走入了 onPause -> onStop - > onDestroyView 方法,已经被销毁回收了,我们第一个页面上的数据已经不存在了。

当我们再次滑回第二个页面时

在这里插入图片描述
第一个页面被重新创建。

我们滑到第一个页面时

在这里插入图片描述

第三个页面被销毁。

三、根据实际的应用情况

问题1. :

滑动到第三个页面是第一个页面会被销毁,页面上的数据都会丢失,很不友好,尽管这能减少内存的使用,但正常情况下,宁愿多用点内存,也要保存这个页面。
解决:通过
mainViewPage.setOffscreenPageLimit(3);// 设置成3,或者自己需要长期保存的页面数(最好不超过5个)

问题2. :

进入第一个页面时,会自己加载第二个页面的信息。这样会造成不必要的内存占用。比如我只使用第一个页面,第二个页面我不看,但第二个页面已经创建成功了,数据已经都加载好了,就等着你滑动过去,显示出来了(setUserVisibleHint 方法参数返回true)。这样对于需要使用来说,很友好,滑过去就可以看到,但会占内存,这就需要使用懒加载方法。
解决:Fragment懒加载基类(只针对懒加载,可以根据自己加内容,牛刀油一些。)

BaseFragment

public abstract class BaseFragment extends Fragment {
    
    

    /**
     * 是否已经初始化完成
     * 是否已经进入过页面
     * 是否正在显示
     * */
    private boolean isPrepareView,isInitData,isVisibleToUser;

    /**
     * 第一次进入页面
     */
    public void lazyInitData(){
    
    
        if (!isInitData && isVisibleToUser && isPrepareView) {
    
    
            isInitData = true;
            firstData();
        }
    }

    protected abstract void initData();

    protected abstract void firstData();


    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
    
    
        super.setUserVisibleHint(isVisibleToUser);
        this.isVisibleToUser = isVisibleToUser;
        if (isInitData){
    
    
            if (!isVisibleToUser){
    
    
                // 取消焦点时,做的操作
            }else {
    
    
                // 成功加载后,进入页面所进行的操作
                initData();
            }
        }else {
    
    
            // 第一次 进入页面 所进行的操作
            lazyInitData();
        }
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    
    
        super.onActivityCreated(savedInstanceState);

        initView(); // 布局绑定一些,可以放着,也可以放onCreateView里

        // 根据之前的生命周期发现,第一个页面会先走setUserVisibleHint 返回true,再走到该方法创建,所有这里这需要加。
        lazyInitData();

    }

    protected abstract void initView();


    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
    
    
        super.onViewCreated(view, savedInstanceState);
        isPrepareView = true;
    }

    public abstract int getLayoutId();

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    
    
        return inflater.inflate(getLayoutId(),container,false);
    }
}

FirstFragment

public class FirstFragment extends BaseFragment{
    
    

    private static final String TAG = "FirstFragment";

    @Override
    protected void initView() {
    
    
        Log.d(TAG, "initView: " + "绑定布局中.....");
    }


    @Override
    protected void initData() {
    
    
        Log.d(TAG, "initData: " + "再次进入页面加载数据.....");
    }

    @Override
    protected void firstData() {
    
    
        Log.d(TAG, "firstData: " + "第一次进入页面加载数据.....");
    }

    @Override
    public int getLayoutId() {
    
    
        return R.layout.fragment_first;
    }
}

接下来就是运行,看日志!

刚进入

在这里插入图片描述

滑到第二个页面

在这里插入图片描述

滑到第三个页面

在这里插入图片描述

返回第二个页面

在这里插入图片描述

返回第一个页面

在这里插入图片描述

总结:到这里就就算结束了,真正做到了滑到哪个fragment加载哪个fragment数据。 如果内容上有问题或者疏忽, 请指正批评。感谢!!!

猜你喜欢

转载自blog.csdn.net/qq_40166103/article/details/115400550