ViewPager两种适配器显示Fragment时的生命周期探究

viewpager可以用来实现多个Fragment显示并可左右滑动的功能。ViewPager有两种不同的适配器来显示Fragment,下面将分别探讨这两种显示方式Fragment的生命周期变化有何不同。
布局为上下两个不同apater的ViewPager。
Fragment标识为1A,2B,3C,4D共4个对象,从1A滑动到4D记录并分析对应的生命周期变化。
这里写图片描述
左右各预先加载一个视图,默认值为1,由下述方法决定

public void setOffscreenPageLimit(int limit) {
        if (limit < DEFAULT_OFFSCREEN_PAGES) {
            Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to "
                    + DEFAULT_OFFSCREEN_PAGES);
            limit = DEFAULT_OFFSCREEN_PAGES;
        }
        if (limit != mOffscreenPageLimit) {
            mOffscreenPageLimit = limit;
            populate();
        }
    }

1.FragmentPagerAdapter

左右滑动时各个Fragment的生命周期变化

//界面初始加载显示1A,预先加载2B界面(一个完整的Fragment生命周期)
09-10 20:47:50.270 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onAttach
    null:null->onCreate
    null:null->onAttach
09-10 20:47:50.276 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onCreate
09-10 20:47:50.277 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例1A->onCreateView
09-10 20:47:50.284 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例1A->onActivityCreated
09-10 20:47:50.285 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例1A->onStart
    FragmentPager:示例1A->onResume
09-10 20:47:50.286 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例2B->onCreateView
09-10 20:47:50.288 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例2B->onActivityCreated
09-10 20:47:50.293 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例2B->onStart
09-10 20:47:50.294 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例2B->onResume
//从1滑动到4
//滑动到2B界面时,预先加载完成3C的界面
09-10 20:49:05.709 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onAttach
09-10 20:49:05.710 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onCreate
09-10 20:49:05.714 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例3C->onCreateView
09-10 20:49:05.720 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例3C->onActivityCreated
    FragmentPager:示例3C->onStart
    FragmentPager:示例3C->onResume

//滑动到3C界面时,预先加载4D的Frgment
09-10 20:49:08.020 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onAttach
    null:null->onCreate

//因为viewpager默认加载是左右各一项,所以当滑动到3C时,1A界面会被销毁
09-10 20:49:08.021 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例1A->onPause
    FragmentPager:示例1A->onStop
    FragmentPager:示例1A->onDestroyView

//销毁完1A视图时开始预先显示4D的界面
09-10 20:49:08.022 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例4D->onCreateView
09-10 20:49:08.026 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例4D->onActivityCreated
    FragmentPager:示例4D->onStart
09-10 20:49:08.027 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例4D->onResume

//滑动到4D时,销毁2B的视图
09-10 20:49:09.626 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentPager:示例2B->onPause
    FragmentPager:示例2B->onStop
    FragmentPager:示例2B->onDestroyView

2.FragmentStatePagerAdapter

//界面初始加载显示1A,预先加载2B界面(一个完整的Fragment生命周期)
09-10 20:47:50.297 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onAttach
    null:null->onCreate
09-10 20:47:50.298 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onAttach
09-10 20:47:50.299 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onCreate
09-10 20:47:50.300 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例1A->onCreateView
09-10 20:47:50.305 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例1A->onActivityCreated
09-10 20:47:50.307 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例1A->onStart
    FragmentState:示例1A->onResume
09-10 20:47:50.308 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例2B->onCreateView
09-10 20:47:50.312 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例2B->onActivityCreated
09-10 20:47:50.314 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例2B->onStart
    FragmentState:示例2B->onResume

//从1滑动到4
//滑动到2B界面时,预先加载完成3C的界面
09-10 20:50:37.133 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onAttach
09-10 20:50:37.134 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onCreate
    FragmentState:示例3C->onCreateView
09-10 20:50:37.138 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例3C->onActivityCreated
09-10 20:50:37.140 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例3C->onStart
    FragmentState:示例3C->onResume

//滑动到3C界面时,先保存将要销毁的1A的状态,后再预先加载4D的Frgment
09-10 20:50:38.863 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例1A->onSaveInstanceState
09-10 20:50:38.867 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: null:null->onAttach
    null:null->onCreate

//开始执行1A的销毁过程
09-10 20:50:38.869 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例1A->onPause
    FragmentState:示例1A->onStop
    FragmentState:示例1A->onDestroyView

//FragmentState会将1A的对象给销毁掉,而FragmentPager只会销毁视图,所以以下方法FragmentPager将不会执行
09-10 20:50:38.870 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例1A->onDestroy
    FragmentState:示例1A->onDetach

//销毁完1A视图时开始预先显示4D的界面
09-10 20:50:38.871 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例4D->onCreateView
09-10 20:50:38.876 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例4D->onActivityCreated
    FragmentState:示例4D->onStart
09-10 20:50:38.877 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例4D->onResume

//滑动到4D时,销毁2B的Fragment对象
09-10 20:50:40.150 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例2B->onSaveInstanceState
09-10 20:50:40.153 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例2B->onPause
    FragmentState:示例2B->onStop
    FragmentState:示例2B->onDestroyView
09-10 20:50:40.156 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例2B->onDestroy
09-10 20:50:40.157 15317-15317/cn.pigdreams.blogdemo D/BLOG_DEMO: FragmentState:示例2B->onDetach

3.总结

  • FragmentPagerAdapter只是销毁Fragment的视图,对象并未销毁,继续由Activity持有。而FragmentStatePagerAdapter则会销毁Fragment的对象,Activity不再持有该Fragment对象。
  • FragmentPagerAdapter适用于显示较少Fragment的情况,
  • FragmentStatePagerAdapter最大的特点是Fragment将会执行onSaveInstanceState保存状态,并且是在onPause()之前执行

这里写图片描述

4.源码分析

两者的主要区别在于

FragmentPagerAdapter

  @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
        if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object
                + " v=" + ((Fragment)object).getView());
        //Detach the given fragment from the UI,只是移除Fragment的视图
        mCurTransaction.detach((Fragment)object);
    }

FragmentStatePagerAdapter

 @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        Fragment fragment = (Fragment) object;

        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
        if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object
                + " v=" + ((Fragment)object).getView());
        while (mSavedState.size() <= position) {
            mSavedState.add(null);
        }
        mSavedState.set(position, fragment.isAdded()
                ? mFragmentManager.saveFragmentInstanceState(fragment) : null);
        mFragments.set(position, null);
        //直接移除Fragment对象
        mCurTransaction.remove(fragment);
    }
发布了92 篇原创文章 · 获赞 68 · 访问量 25万+

猜你喜欢

转载自blog.csdn.net/pigdreams/article/details/82598240