(4.1.8.8)Fragment生命周期详解

来源:互联网 发布:js动态修改style属性 编辑:程序博客网 时间:2024/05/22 08:01

关于Fragment的生命周期,博主写过Activity与Fragment生命周期详解,基本上把Fragment的生命周期详细介绍过,但是那仅仅是创建一个Fragmnet时的生命周期,而事实上Fragment的出现是为了动态的切换显示不同的界面的,因此我们对于Fragment的生命周期的了解不能仅仅停留在创建一个Fragment的时候,而是应该能够知道调用不同API切换Fragment时的生命周期是怎么的,如调用add(),hide(),show()与replace()时它们的生命周期的不同,博主在昨天360视频面试的时候就被问到过。

一使用静态方式时的生命周期:

正如我们在Activity与Fragment生命周期详解中所介绍的,此时Fragment的生命周期为

onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume, onPause, onStop, onDestroyView, onDestroy, onDetach.

可以参看Activity与Fragment生命周期详解中相关内容的官方图片理解,

1其中当创建一个Fragment首次展示其布局界面时:

onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment处于运行状态

2当关闭手机屏幕或者手机屏幕变暗或直接按home键返回桌面时,其生命周期方法调用的顺序是

onPause, onStop

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

onStart, onResume

4当对Fragment按返回键时:

onPause, onStop, onDestroyView, onDestroy, onDetach.


二使用FragmentManager动态的添加Fragment

这块是本博客讲解的重点,因为动态添加涉及到Fragment的切换,所以我们先定义两个Fragment。代码如下:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public class FragOne extends Fragment {  
  2.     private static final String TAG = FragOne.class.getSimpleName();  
  3.   
  4.     @Override  
  5.     public void onAttach(Activity activity) {  
  6.         super.onAttach(activity);  
  7.         Log.i(TAG, "onAttach");  
  8.     }  
  9.   
  10.     @Override  
  11.     public void onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         Log.i(TAG, "onCreate");  
  14.     }  
  15.   
  16.     @Override  
  17.     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
  18.         Log.i(TAG, "onCreateView");  
  19.         return inflater.inflate(R.layout.fragment_test_a, nullfalse);  
  20.     }  
  21.   
  22.     @Override  
  23.     public void onViewCreated(View view, Bundle savedInstanceState) {  
  24.         Log.i(TAG, "onViewCreated");  
  25.         super.onViewCreated(view, savedInstanceState);  
  26.     }  
  27.   
  28.     @Override  
  29.     public void onDestroy() {  
  30.         Log.i(TAG, "onDestroy");  
  31.         super.onDestroy();  
  32.     }  
  33.   
  34.     @Override  
  35.     public void onDetach() {  
  36.         Log.i(TAG, "onDetach");  
  37.         super.onDetach();  
  38.     }  
  39.   
  40.     @Override  
  41.     public void onDestroyView() {  
  42.         Log.i(TAG, "onDestroyView");  
  43.         super.onDestroyView();  
  44.     }  
  45.   
  46.     @Override  
  47.     public void onStart() {  
  48.         Log.i(TAG, "onStart");  
  49.         super.onStart();  
  50.     }  
  51.   
  52.     @Override  
  53.     public void onStop() {  
  54.         Log.i(TAG, "onStop");  
  55.         super.onStop();  
  56.     }  
  57.   
  58.     @Override  
  59.     public void onResume() {  
  60.         Log.i(TAG, "onResume");  
  61.         super.onResume();  
  62.     }  
  63.   
  64.     @Override  
  65.     public void onPause() {  
  66.         Log.i(TAG, "onPause");  
  67.         super.onPause();  
  68.     }  
  69.   
  70.     @Override  
  71.     public void onActivityCreated(Bundle savedInstanceState) {  
  72.         Log.i(TAG, "onActivityCreated");  
  73.         super.onActivityCreated(savedInstanceState);  
  74.     }  
  75. }  
第二个Fragment

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public class FragTwo extends Fragment {  
  2.     private static final String TAG = FragTwo.class.getSimpleName();  
  3.   
  4.     @Override  
  5.     public void onAttach(Activity activity) {  
  6.         super.onAttach(activity);  
  7.         Log.i(TAG, "onAttach");  
  8.     }  
  9.   
  10.     @Override  
  11.     public void onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         Log.i(TAG, "onCreate");  
  14.     }  
  15.   
  16.     @Override  
  17.     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
  18.         Log.i(TAG, "onCreateView");  
  19.         return inflater.inflate(R.layout.fragment_test_b, nullfalse);  
  20.     }  
  21.   
  22.     @Override  
  23.     public void onViewCreated(View view, Bundle savedInstanceState) {  
  24.         Log.i(TAG, "onViewCreated");  
  25.         super.onViewCreated(view, savedInstanceState);  
  26.     }  
  27.   
  28.     @Override  
  29.     public void onDestroy() {  
  30.         Log.i(TAG, "onDestroy");  
  31.         super.onDestroy();  
  32.     }  
  33.   
  34.     @Override  
  35.     public void onDetach() {  
  36.         Log.i(TAG, "onDetach");  
  37.         super.onDetach();  
  38.     }  
  39.   
  40.     @Override  
  41.     public void onDestroyView() {  
  42.         Log.i(TAG, "onDestroyView");  
  43.         super.onDestroyView();  
  44.     }  
  45.   
  46.     @Override  
  47.     public void onStart() {  
  48.         Log.i(TAG, "onStart");  
  49.         super.onStart();  
  50.     }  
  51.   
  52.     @Override  
  53.     public void onStop() {  
  54.         Log.i(TAG, "onStop");  
  55.         super.onStop();  
  56.     }  
  57.   
  58.     @Override  
  59.     public void onResume() {  
  60.         Log.i(TAG, "onResume");  
  61.         super.onResume();  
  62.     }  
  63.   
  64.     @Override  
  65.     public void onPause() {  
  66.         Log.i(TAG, "onPause");  
  67.         super.onPause();  
  68.     }  
  69.   
  70.     @Override  
  71.     public void onActivityCreated(Bundle savedInstanceState) {  
  72.         Log.i(TAG, "onActivityCreated");  
  73.         super.onActivityCreated(savedInstanceState);  
  74.     }  
  75. }  
可以看到这两个Fragment的代码基本上完全相同,都是重写了Fragment中相关的生命周期函数。


一当没使用addToBackStack函数时。

1使用replace()函数时:

当我们使用replace初次显示一个Fragment时,此时代码如下:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();  
  2.  fragOne = new FragOne();  
  3.  fragmentTransaction.replace(R.id.frag_container, fragOne, fragNames[0]);  
  4.  fragmentTransaction.commit();  
此时的生命周期和上述讲述的完全相同,即onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment处于运行状态。


当我们使用replace()来替换一个已经存在的Fragment时(如腾讯QQ中当我们点击不同的底部按钮时会替换之前的Fragment),此时代码如下:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public void onClick(View v) {  
  2.         FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();  
  3.         switch (v.getId()) {  
  4.             case R.id.button1:  
  5.                 if (fragOne == null) {  
  6.                     fragOne = new FragOne();  
  7.                     fragmentTransaction.replace(R.id.frag_container, fragOne, fragNames[0]);  
  8. //                    fragmentTransaction.addToBackStack(fragNames[0]);  
  9.                 } else {  
  10.                     Fragment fragment = fragmentManager.findFragmentByTag(fragNames[0]);  
  11.                     fragmentTransaction.replace(R.id.frag_container, fragment, fragNames[0]);  
  12.                 }  
  13.                 break;  
  14.             case R.id.button2:  
  15.                 if (fragTwo == null) {  
  16.                     fragTwo = new FragTwo();  
  17.                     fragmentTransaction.replace(R.id.frag_container, fragTwo, fragNames[1]);  
  18. //                    fragmentTransaction.addToBackStack(fragNames[1]);  
  19.                 } else {  
  20.                     Fragment fragment = fragmentManager.findFragmentByTag(fragNames[1]);  
  21.                     fragmentTransaction.replace(R.id.frag_container, fragment, fragNames[1]);  
  22.                 }  
  23.                 break;  
  24.             default:  
  25.                 break;  
  26.         }  
  27.         fragmentTransaction.commit();  
  28.     }  
可以看到在上述代码中,我们将addToBackStack函数的调用注释起来,表示此时不适用该功能。此时的运行顺序为:


可以看到第一个Fragment的调用顺序为:onPause, onStop, onDestroyView, onDestroy, onDetach,这表明fragOne已经被FragmentManager销毁了,取而代之的是第二个Fragment,这也与replace()函数的名称和不适用addToBackStack相符合(即替换且不添加到Fragment返回栈中,既然是替换当然得去除前一个,添加第二个Fragment)

这说明,在使用replace添加Fragment时如果没有调用addToBackStack方式的话,当FragmentManager替换Fragment时,是不保存Fragment的状态的,此时第二个Fragment将会直接替换前一个Fragment。

二使用addToBackStack函数时。

当我们使用replace函数且设置addToBackStack函数初次显示一个Fragment运行结果为:onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment处于运行状态。即与不使用addToBackStack函数时的运行结果相同。

当我们使用replace函数且设置addToBackStack函数来替换之前显示的Fragmen't时运行结果为:


可以看到与之前的不使用addToBackStack相比,fragTwo的生命周期不受影响,而fragOne的生命周期和不使用addBackToStack函数相比,只存在三种状态的切换:onPause

onStop,onDestroyView。前者很好理解,因为addToBackStack函数顾名思义就是添加到回退栈中的意思,即当一个Fragment被另一个Fragment替换时会将之前的添加到回退栈中,因此也很好理解fragTwo的生命周期不受影响,因为是将被替换的添加到回退栈中,所以替换者不受影响。另外fragOne状态只到达onDestroyView,而无onDestroy,

onDetach。这说明fragOne仅仅只是界面被销毁onDestroyView,而fragOne对象的实例依然被保存在FragmentManager中(因为无onDestroy,onDetach),它的部分状态依然被保存在FragmentManager中。我们可以来验证一下:


我们点击按钮切换,让fragOne来替换当前显示的fragTwo,此时运行结果如下:


可以看到此时运行结果与fragTwo替换fragOne时fragOne的生命周期调用顺序非常相似,而且可以看到fragOne的生命周期是直接从onCreateView开始的,这也刚好对应上面的fragOne被fragTwo替换时生命周期到达onDestroyView,即之前的fragOne仅仅销毁了视图,而fragOne对象的实例依然被保存在FragmentManager中,所以此时只需要创建视图,即直接从onCreateView开始。


三使用show()/hide()函数时:首先要明白使用show()/hide()时一般是会使用addToBackStack,,因为要使用show()/hide()前提是该Fragment实例已经存在,只不过我们是否将其界面显示出来而已,因此我们需要使用addToBackStack函数将一个Fragment的实例对象保存在Fragment的回退栈中。此时代码如下:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();  
  2.         switch (v.getId()) {  
  3.             case R.id.button1:  
  4.                 hideAllFrags(fragmentTransaction);  
  5.                 if (fragA == null) {  
  6.                     fragOne = new FragOne();  
  7.                     fragmentTransaction.add(R.id.frag_container, fragOne, fragNames[0]);  
  8.                     fragmentTransaction.addToBackStack(fragNames[0]);  
  9.                 } else {  
  10.                     fragmentTransaction.show(fragOne);  
  11.                 }  
  12.                 break;  
  13.             case R.id.button2:  
  14.                 hideAllFrags(fragmentTransaction);  
  15.                 if (fragTwo == null) {  
  16.                     fragTwo = new FragTwo();  
  17.                     fragmentTransaction.add(R.id.frag_container, fragTwo, fragNames[1]);  
  18.                     fragmentTransaction.addToBackStack(fragNames[1]);  
  19.                 } else {  
  20.                     fragmentTransaction.show(fragTwo);  
  21.                 }  
  22.                 break;  
  23.             default:  
  24.                 break;  
  25.         }  
  26. fragmentTransaction.commit();  

当我们使用add()/show()函数初次显示一个Fragment运行结果为:onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment处于运行状态。这个很好理解,不再赘述。

当我们点击按钮切换显示第二个Fragment时运行结果为:


可以看到此时fragOne无输出,表示fragOne的生命周期不受影响,而fragTwo的输出结果与直接初次显示fragTwo时是一样的。其实这也很好理解因为在add()/show()/hide()顾名思义就是添加显示隐藏的意思,它都不会对另外的Fragment的生命周期起作用。


0 0
原创粉丝点击