美文网首页android UI系列专题
Android ViewPager中Fragment的生命周期&

Android ViewPager中Fragment的生命周期&

作者: Alien水哥 | 来源:发表于2017-11-09 13:31 被阅读284次

    首先,我们创建一个Activity和一个Fragment,并在Fragment的各个生命周期打好日志,并把Fragments丢进Viewpager,这里我们往Viewpager里丢了3个Fragment,够用了。
    同时设置Viewpager.adapter = FragmentPagerAdapter

    0.刚打开Avtivity

    viewpager刚进入时刻
    viewpager刚进入时刻:viewpager显示fragment1,fragment2同时被预加载,currentItem = 0

    1.往左翻动一页


    此时滑动一页来到第二页,currentItem = 1,可以看到前2个fragment没有生命周期的变化,只是第三个faragment走了一遍前2个走过的路,这里大家也都知道,viewpager有个setOffscreenPageLimit()方法,用来确认左右两边同时各加载几个页面,默认为1,这里adapter.getCount()==3所有滑倒中间的时候,所有页面都是在活跃的状态,所以前两个页面不会有生命周期的调用。

    2.继续往左翻动一页


    再次滑到下一页,currentItem = 2 可以看到第2、3个页面生命周期没有变化,只有第一个页面经历了onPause->onStop->onDestroyView这么一个变化。第一个页面的视图被销毁了。

    3.往右翻动一页


    此时currentItem=1,可以看到第一个页面的Fragment的视图重建了,从onCreateView开始走一遍。不过并没有经历onAttach/onCreate

    3.按返回键退出Activity


    fragment生命周期有这些变化,可以看到第2、3个页面也走过了onPause->onStop->onDestroyView这么一个变化,由于第一个页面在上一步就销毁了view走过了这个步骤,所以接下来就是所有的Fragment经历onDestroy->onDetach这么一个过程

    接下来设置viewpager.adapter = FragmentStatePagerAdapter

    0.首先,老规矩,刚打开Activity时候的状态

    viewpager刚进入时刻
    可以看到没有任何一丢丢的变化,跟上面同时期的状态是一毛一样的。currentItem = 0

    1.往左翻动一页


    可以看到,跟上面同时期还是没有any变化......currentItem = 1

    2.继续往左翻动一页


    好吧,咱继续翻,到currentItem = 2,这里有区别了。可以看到第一个页面还是经过了onPause->onStop->onDestoryView这么一个过程,不过在此之前,调用了onSaveInstanceState来保存一些必要的信息,在此后,该fragment也随即从内存中销毁,因为经过了onDestroy->onDetach这么一个过程,与activity脱离关系。那么我们再往右滑动一页,回到currentItem=1的时候。

    3.往右翻动一页


    可以看到此时第一个页面的fragment重建了,重新走了一遍onAttach->...->onResume这么个过程,并且在其中有传入saveInstanceState的方法中传入了一个不为null的对象,日志中我们可以看到bundle中有个testKey=0,是因为我们重写了fragment的一个方法:
     override fun onSaveInstanceState(outState: Bundle?) {
            super.onSaveInstanceState(outState)
            outState?.putInt("testKey",arguments.getInt("index"))
            log("onSaveInstanceState")
        }
    

    这里arguments中的int extra是自己传进去的。

    那么我们看下FragmentStateViewPager的源码:

     @Override
        public Object instantiateItem(ViewGroup container, int position) {
            ...
            if (mSavedState.size() > position) {
                Fragment.SavedState fss = mSavedState.get(position);
                if (fss != null) {
                    fragment.setInitialSavedState(fss);
                }
            }
            while (mFragments.size() <= position) {
                mFragments.add(null);
            }
            ...
            return fragment;
        }
        
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            
            while (mSavedState.size() <= position) {
                mSavedState.add(null);
            }
            mSavedState.set(position, fragment.isAdded()
                    ? mFragmentManager.saveFragmentInstanceState(fragment) : null);
            mFragments.set(position, null);
    
            ...
        }
    
    

    省略掉无关代码,就剩下以上这些,可以看到FragmentStateViewPager$destroyItem中为我们保存了Fragment退出时的状态,而在FragmentStateViewPager$instantiateItem中为新建的Fragment设置了初始化state,以此达到为我们保存Fragment state的目的。

    总结FragmentPagerAdapter&FragmentStatePagerAdapter:

    相似点:

    他们都无法保存视图,即在offScreenLimit之外的Fragment总是要被destroyView。

    不同点:

    最大的区别就是对于在offScreenLimit之外的Fragment,FragmentPagerAdapter会销毁试图,但Fragmnet不会detach,也就是Fragment还是在内存中的,当需要再次显示时他会createView,这意味着我们可以在Fragment对象中保存一些我们需要存储的信息,createView的时候做自己的选择。

    而FragmentStatePagerAdapter就不同了,相同的情况下对于在offScreenLimit之外的Fragment,被destroyView只有还有detach,也就是此前的Fragment对象不复存在了,那么我们肯定不能在Fragment中保存必要的信息了,此时可以重写onSaveInstanceState来保存必要信息,并在onCreateView的时候重新拿出来用。FragmentStatePagerAdapter中为我们保存这些state是通过一个ArrayList来实现的,意味着他是记着Fragment的index作为key来保存或者取出的,


    那么对于我们开发者来说,可以在此做个选择。在使用Viewpager中Fragment页面较少的情况可以选择FragmentPagerAdapter,这样代码会少几行,简单。

    在viewpager中Fragment页面比较多的时候选择FragmentStatePagerAdapter来减少内存占用,Fragment试图销毁的同时detach Fargment,但需要通过saveInstaceState来达到保存关键信息的目的。

    至于Fragment的生命周期,关键的应该都已经在上面出现过了,有时间再添加上hide/show/repalce时候的生命周期。

    相关文章

      网友评论

        本文标题:Android ViewPager中Fragment的生命周期&

        本文链接:https://www.haomeiwen.com/subject/gaspmxtx.html