zoukankan      html  css  js  c++  java
  • Fragment生命周期总结

    原文链接:http://www.php100.com/html/it/biancheng/2015/0120/8419.html

    参考:http://blog.csdn.net/lmj623565791/article/details/37992017

    Fragment是Android中的重要组件,在Android 3.0的时候添加进来。

    关于Fragment的生命周期,我相信了解过的开发人员都应该把以下方法脱口而出:onAttach, onCreate, onCreateView, onViewCreated, onActivityCreated, onStart, onResume, onPause, onStop, onDestroyView, onDestroy, onDetach.

    Fragment以静态的方式,即通过在布局文件中以其它控件的方式设置时,它的生命周期随所在Activity的生命周期而发生变化。此时其生命周期的方法调用过程是这样的:

    1,当首次展示布局页面时,其生命周期方法调用的顺序是:

    2,而当关闭手机屏幕或者手机屏幕变暗时,其其生命周期方法调用的顺序是:

    3,当再次对手机屏幕解锁或者手机屏幕变亮时,其生命周期方法调用的顺序是:

    4,而当对当前Fragment所在屏幕按返回键时,其生命周期方法调用的顺序是:

    1 01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragA: onPause
    2 01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragA: onStop
    3 01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragA: onDestroyView
    4 01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragA: onDestroy
    5 01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragA: onDetach

    但是当使用FragmentManager动态的管理Fragment并且涉及到是否addToBackStack时,其生命周期的展现就略微显得有些复杂了。但是还没有复杂到无法理解。

    好,下面,我们就探究一下这些问题。

    首先,我们重写了两个Fragment,主要是重写了它们的生命周期方法,通过在其生命周期方法中打印出Log的方式来显示其方法的调用。

    两个类分别是:

    package com.yeepay.fraglifecircletest.frag;
    
    import android.app.Activity;
    import android.app.Fragment;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    import com.yeepay.fraglifecircletest.R;
    
    public class FragA extends Fragment {
        private static final String TAG = FragA.class.getSimpleName();
    
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            Log.i(TAG, "onAttach");
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.i(TAG, "onCreate");
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            Log.i(TAG, "onCreateView");
            return inflater.inflate(R.layout.fragment_test_a, null, false);
        }
    
        @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {
            Log.i(TAG, "onViewCreated");
            super.onViewCreated(view, savedInstanceState);
        }
    
        @Override
        public void onDestroy() {
            Log.i(TAG, "onDestroy");
            super.onDestroy();
        }
    
        @Override
        public void onDetach() {
            Log.i(TAG, "onDetach");
            super.onDetach();
        }
    
        @Override
        public void onDestroyView() {
            Log.i(TAG, "onDestroyView");
            super.onDestroyView();
        }
    
        @Override
        public void onStart() {
            Log.i(TAG, "onStart");
            super.onStart();
        }
    
        @Override
        public void onStop() {
            Log.i(TAG, "onStop");
            super.onStop();
        }
    
        @Override
        public void onResume() {
            Log.i(TAG, "onResume");
            super.onResume();
        }
    
        @Override
        public void onPause() {
            Log.i(TAG, "onPause");
            super.onPause();
        }
    
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            Log.i(TAG, "onActivityCreated");
            super.onActivityCreated(savedInstanceState);
        }
    }
    
    FragA.java
    package com.yeepay.fraglifecircletest.frag;
    
    import android.app.Activity;
    import android.app.Fragment;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    import com.yeepay.fraglifecircletest.R;
    
    public class FragB extends Fragment {
        private static final String TAG = FragB.class.getSimpleName();
    
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            Log.i(TAG, "onAttach");
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.i(TAG, "onCreate");
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            Log.i(TAG, "onCreateView");
            return inflater.inflate(R.layout.fragment_test_b, null, false);
        }
    
        @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {
            Log.i(TAG, "onViewCreated");
            super.onViewCreated(view, savedInstanceState);
        }
    
        @Override
        public void onDestroy() {
            Log.i(TAG, "onDestroy");
            super.onDestroy();
        }
    
        @Override
        public void onDetach() {
            Log.i(TAG, "onDetach");
            super.onDetach();
        }
    
        @Override
        public void onDestroyView() {
            Log.i(TAG, "onDestroyView");
            super.onDestroyView();
        }
    
        @Override
        public void onStart() {
            Log.i(TAG, "onStart");
            super.onStart();
        }
    
        @Override
        public void onStop() {
            Log.i(TAG, "onStop");
            super.onStop();
        }
    
        @Override
        public void onResume() {
            Log.i(TAG, "onResume");
            super.onResume();
        }
    
        @Override
        public void onPause() {
            Log.i(TAG, "onPause");
            super.onPause();
        }
    
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            Log.i(TAG, "onActivityCreated");
            super.onActivityCreated(savedInstanceState);
        }
    }
    
    FragB.java

    1,当我们通过以下方式添加FragA时,

    1 FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    2 fragA = new FragA();
    3                     fragmentTransaction.replace(R.id.frag_container, fragA, fragNames[0]);
    4 fragmentTransaction.commit();

    它的生命周期展示方式是同在布局文件中静态设置的表现一模一样的,这里不再详细展开,大家可以查看一下以上内容。

    2,当我们以如下方式展示FragA并且没有addToBackStack时,

    @Override
        public void onClick(View v) {
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            switch (v.getId()) {
                case R.id.button1:
                    if (fragA == null) {
                        fragA = new FragA();
                        fragmentTransaction.replace(R.id.frag_container, fragA, fragNames[0]);
    //                    fragmentTransaction.addToBackStack(fragNames[0]);
                    } else {
                        Fragment fragment = fragmentManager.findFragmentByTag(fragNames[0]);
                        fragmentTransaction.replace(R.id.frag_container, fragment, fragNames[0]);
                    }
                    break;
                case R.id.button2:
                    if (fragB == null) {
                        fragB = new FragB();
                        fragmentTransaction.replace(R.id.frag_container, fragB, fragNames[1]);
    //                    fragmentTransaction.addToBackStack(fragNames[1]);
                    } else {
                        Fragment fragment = fragmentManager.findFragmentByTag(fragNames[1]);
                        fragmentTransaction.replace(R.id.frag_container, fragment, fragNames[1]);
                    }
                    break;
                default:
                    break;
            }
            fragmentTransaction.commit();
        }

    FragA生命周期调用顺序是:

    此时,如果再点击另外一个按钮B,将FragB展示出来,FragA和FragB的生命周期展示方式是:

    可以看到,FragA调用顺序为onPause, onStop, onDestroyView, onDestroy, onDetach.这说明,FragA已经被FragmentManager完全抛弃了,取而代之的是FragB的完全展现。而如果此时按返回键的话,FragB的生命周期也将是onPause, onStop, onDestroyView, onDestroy, onDetach。这说明,在添加Fragment时如果没有调用addToBackStack方式的话,当FragmentManager更换Fragment时,是不保存Fragment的状态的。

    3,下面我们在替换Fragment时顺便addToBackStack,则其生命周期展现方式是:

    replace FragA and addToBackStack
    ########################################################################################
    01-13 17:08:43.359    3102-3102/com.yeepay.fraglifecircletest I/FragA: onAttach
    01-13 17:08:43.359    3102-3102/com.yeepay.fraglifecircletest I/FragA: onCreate
    01-13 17:08:43.359    3102-3102/com.yeepay.fraglifecircletest I/FragA: onCreateView
    01-13 17:08:43.359    3102-3102/com.yeepay.fraglifecircletest I/FragA: onViewCreated
    01-13 17:08:43.359    3102-3102/com.yeepay.fraglifecircletest I/FragA: onActivityCreated
    01-13 17:08:43.359    3102-3102/com.yeepay.fraglifecircletest I/FragA: onStart
    01-13 17:08:43.359    3102-3102/com.yeepay.fraglifecircletest I/FragA: onResume

    可以看得出来,此时的生命周期方法调用是跟没有addToBackStack时没有任何区别的。

    然后通过点击按钮B,使用FragB来替换FragA,此时FragA和FragB的生命周期方法调用顺序是:

    and then replace FragB and addToBackStack
    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragA: onPause
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragA: onStop
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragA: onDestroyView
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragB: onAttach
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragB: onCreate
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragB: onCreateView
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragB: onViewCreated
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragB: onActivityCreated
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragB: onStart
    01-13 17:08:46.959    3102-3102/com.yeepay.fraglifecircletest I/FragB: onResume

    由此可以看出,FragA生命周期方法只是调用到了onDestroyView,而onDestroy和onDetach则没有被调用,这说明FragA的界面已经被销毁了,但是FragmentManager并没有完全销毁FragA,FragA依然有状态保存在FragmentManager里面。

    然后再点击按钮A,使用FragA来替换当前显示的FragB,此时FragA和FragB的生命周期方法调用顺序为:

    and then replace FragA again
    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    01-13 17:08:51.869    3102-3102/com.yeepay.fraglifecircletest I/FragB: onPause
    01-13 17:08:51.869    3102-3102/com.yeepay.fraglifecircletest I/FragB: onStop
    01-13 17:08:51.869    3102-3102/com.yeepay.fraglifecircletest I/FragB: onDestroyView
    01-13 17:08:51.869    3102-3102/com.yeepay.fraglifecircletest I/FragA: onCreateView
    01-13 17:08:51.869    3102-3102/com.yeepay.fraglifecircletest I/FragA: onViewCreated
    01-13 17:08:51.869    3102-3102/com.yeepay.fraglifecircletest I/FragA: onActivityCreated
    01-13 17:08:51.869    3102-3102/com.yeepay.fraglifecircletest I/FragA: onStart
    01-13 17:08:51.869    3102-3102/com.yeepay.fraglifecircletest I/FragA: onResume

    可以看到,FragB的生命方法调用顺序是跟FragB替换FragA时FragA的调用顺序一致的,作用就是只销毁了视图,但是依然保留了Fragment的状态。而此时FragA的调用则值得注意,此时FragA直接从onCreateView调起,也就是说只是重新创建了视图,而依然使用上次被替换时的Fragment状态。

    OK,说到此时,是否对Fragment的生命周期方法调用在是否addToBackStack时不同有所更加深入的了解了呢?

    好吧,最后一个问题。是关于Fragment在FragmentManager管理时,show和hide时的生命周期方法调用。

    此时的调用实现方式为:

    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            switch (v.getId()) {
                case R.id.button1:
                    hideAllFrags(fragmentTransaction);
                    if (fragA == null) {
                        fragA = new FragA();
                        fragmentTransaction.add(R.id.frag_container, fragA, fragNames[0]);
                        fragmentTransaction.addToBackStack(fragNames[0]);
                    } else {
                        fragmentTransaction.show(fragA);
                    }
                    break;
                case R.id.button2:
                    hideAllFrags(fragmentTransaction);
                    if (fragB == null) {
                        fragB = new FragB();
                        fragmentTransaction.add(R.id.frag_container, fragB, fragNames[1]);
                        fragmentTransaction.addToBackStack(fragNames[1]);
                    } else {
                        fragmentTransaction.show(fragB);
                    }
                    break;
                default:
                    break;
            }
    fragmentTransaction.commit();

    细心的话可以发现,在展示Fragment时,我们使用了方法add而非上面用的replace。而且直接addToBackStack。其实这也可以理解,你想,FragmentManager在show或者hide时,肯定是已经存在的,或者如果没有的话,需要添加进来Fragment。这便是在show和hide时,需要注意的地方,即使用add和addToBackStack方法。

    在点击按钮A时,FragA的调用顺序为:

    01-15 16:57:20.390    9225-9225/com.yeepay.fraglifecircletest I/hideAllFrags: hideAllFrags
    01-15 16:57:20.390    9225-9225/com.yeepay.fraglifecircletest I/FragA: onAttach
    01-15 16:57:20.390    9225-9225/com.yeepay.fraglifecircletest I/FragA: onCreate
    01-15 16:57:20.390    9225-9225/com.yeepay.fraglifecircletest I/FragA: onCreateView
    01-15 16:57:20.390    9225-9225/com.yeepay.fraglifecircletest I/FragA: onViewCreated
    01-15 16:57:20.390    9225-9225/com.yeepay.fraglifecircletest I/FragA: onActivityCreated
    01-15 16:57:20.390    9225-9225/com.yeepay.fraglifecircletest I/FragA: onStart
    01-15 16:57:20.390    9225-9225/com.yeepay.fraglifecircletest I/FragA: onResume

    可以看出没有什么不同于以上所言的部分。

    然后,点击按钮B时,FragA和FragB的调用顺序为:

    01-15 16:57:23.360    9225-9225/com.yeepay.fraglifecircletest I/hideAllFrags: hideAllFrags
    01-15 16:57:23.360    9225-9225/com.yeepay.fraglifecircletest I/FragB: onAttach
    01-15 16:57:23.360    9225-9225/com.yeepay.fraglifecircletest I/FragB: onCreate
    01-15 16:57:23.360    9225-9225/com.yeepay.fraglifecircletest I/FragB: onCreateView
    01-15 16:57:23.370    9225-9225/com.yeepay.fraglifecircletest I/FragB: onViewCreated
    01-15 16:57:23.370    9225-9225/com.yeepay.fraglifecircletest I/FragB: onActivityCreated
    01-15 16:57:23.370    9225-9225/com.yeepay.fraglifecircletest I/FragB: onStart
    01-15 16:57:23.370    9225-9225/com.yeepay.fraglifecircletest I/FragB: onResume

    可以看出,FragA并没有调用生命周期方法,这说明是展示FragB时,FragA的生命周期并没有发生变化。而FragB的生命周期与初次点击按钮A时FragA的生命周期方法相同。

    然后再继续点击按钮A和B,此时打印出来的log为:

    1 01-15 16:57:25.220    9225-9225/com.yeepay.fraglifecircletest I/hideAllFrags: hideAllFrags
    2 01-15 16:57:44.990    9225-9225/com.yeepay.fraglifecircletest I/hideAllFrags: hideAllFrags
    3 01-15 16:57:47.350    9225-9225/com.yeepay.fraglifecircletest I/hideAllFrags: hideAllFrags
    4 01-15 16:57:48.020    9225-9225/com.yeepay.fraglifecircletest I/hideAllFrags: hideAllFrags

    这说明在FragA和FragB添加进BackStack之后无论如何地show或者hide,它们的生命周期不再发生变化。

    而当屏幕上锁或变暗,然后再解锁或者变亮时,FragA和FragB的生命周期方法调用顺序为:

    when screen is locked:
    ###########################################################################################
    01-15 16:58:36.840    9225-9225/com.yeepay.fraglifecircletest I/FragA: onPause
    01-15 16:58:36.840    9225-9225/com.yeepay.fraglifecircletest I/FragB: onPause
    01-15 16:58:36.870    9225-9225/com.yeepay.fraglifecircletest I/FragA: onStop
    01-15 16:58:36.880    9225-9225/com.yeepay.fraglifecircletest I/FragB: onStop
    
    when screen is unlocked:
    ##########################################################################################
    01-15 17:05:01.850    9225-9225/com.yeepay.fraglifecircletest I/FragA: onStart
    01-15 17:05:01.850    9225-9225/com.yeepay.fraglifecircletest I/FragB: onStart
    01-15 17:05:01.870    9225-9225/com.yeepay.fraglifecircletest I/FragA: onResume
    01-15 17:05:01.870    9225-9225/com.yeepay.fraglifecircletest I/FragB: onResume

    可以看得出来,两个Fragment都调用了onPause, onStop, onStart, onResume。而且FragA的调用要在FragB之前,这说明跟他们添加进BackStack的顺序有关。

  • 相关阅读:
    iPhone网络编程之--Reachability
    ASIHTTPRequest 详解, http 请求终结者2
    什么情况下使用break关键字? 什么情况下使用Continue关键字? Java如何声明一个数组?JS如何声明一个数组?如何获取数组长度? 如何遍历数组?
    说说三元运算和if...else的相同之处? Switch语句的条件只能接受什么类型的值? 说说do...while和while的区别? 说说for循环的两种写法?
    String类的常用方法
    逻辑结算的结果是什么类型? 比较运算的值是什么类型? 声明字符串有哪几种方式?怎么写? Math类有哪些常用的方法? 三元运算怎么写?
    算术运算有哪些?逻辑运算有哪些?比较运算有哪些?
    Java中8种基本数据类型是哪些?
    Java如何声明变量?JS如何声明变量?
    回顾之前知识: 注释
  • 原文地址:https://www.cnblogs.com/androidstudy/p/5502074.html
Copyright © 2011-2022 走看看