本文转载于 Fragment生命周期详解,感谢博主的付出,转载到此,也是为了自己的工作学习。大家一起进步
简单来说,Fragment 的生命周期可以用下图来表示:
1. onAttach(),该方法是用在Fragment和Activity建立关系的时候调用的,它会携带一个参数Context或者Activity(API < 23时)。
2. onCreate(),与Activity的onCreate()方法一样,都是对象被创建的时候调用,注意,此时Activity并未完成初始化,也就是还没有调用onStart()方法。
3. onCreateView(),这个方法就是在要初始化Fragment界面的时候调用的,这个基本上是必须重写的函数,再此函数中加载布局并返回。
4. onActivityCreate(),这个方法回调的时候表示Activity已经初始化完了,也就是开始继续执行onStart()等后续方法了。
5. onDestroyView(),这个方法是在Fragment所包含的组件被销毁时调用。
6. onDetach(),这个方法是在Fragment从Activity删除或者被替换时调用,当执行了onDestroy()方法后会执行此方法。
这上边有很多生命周期的回调函数与Activity的回调函数名字是一样,他们所完成的功能也基本一致,对其中的一些函数具体说明一下:
一、使用静态方式时的生命周期:
此时Fragment的生命周期为onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume, onPause, onStop, onDestroyView, onDestroy, onDetach.
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。代码如下:
public class FragOne extends Fragment {
private static final String TAG = FragOne.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);
}
}
第二个Fragment
public class FragTwo extends Fragment {
private static final String TAG = FragTwo.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);
}
}
可以看到这两个Fragment的代码基本上完全相同,都是重写了Fragment中相关的生命周期函数。
一、当没使用addToBackStack函数时。
1、使用replace()函数时:
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragOne = new FragOne();
fragmentTransaction.replace(R.id.frag_container, fragOne, fragNames[0]);
fragmentTransaction.commit();
此时的生命周期和上述讲述的完全相同,即onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment处于运行状态。
2、当我们使用replace()来替换一个已经存在的Fragment时(如腾讯QQ中当我们点击不同的底部按钮时会替换之前的Fragment),此时代码如下:
public void onClick(View v) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
switch (v.getId()) {
case R.id.button1:
if (fragOne == null) {
fragOne = new FragOne();
fragmentTransaction.replace(R.id.frag_container, fragOne, 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 (fragTwo == null) {
fragTwo = new FragTwo();
fragmentTransaction.replace(R.id.frag_container, fragTwo, 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();
}
可以看到在上述代码中,我们将addToBackStack函数的调用注释起来,表示此时不适用该功能。此时的运行顺序为:
可以看到第一个Fragment的调用顺序为:onPause, onStop, onDestroyView, onDestroy, onDetach,这表明fragOne已经被FragmentManager销毁了,取而代之的是第二个Fragment,这也与replace()函数的名称和不适用addToBackStack相符合(即替换且不添加到Fragment返回栈中,既然是替换当然得去除前一个,添加第二个Fragment)
这说明,在使用replace添加Fragment时如果没有调用addToBackStack方式的话,当FragmentManager替换Fragment时,是不保存Fragment的状态的,此时第二个Fragment将会直接替换前一个Fragment。
二、使用addToBackStack函数时。
(1)当我们使用replace函数且设置addToBackStack函数初次显示一个Fragment运行结果为:onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment处于运行状态。即与不使用addToBackStack函数时的运行结果相同。
当我们使用replace函数且设置addToBackStack函数来替换之前显示的Fragmen't时运行结果为:
可以看到与之前的不使用addToBackStack相比,fragTwo的生命周期不受影响,而fragOne的生命周期和不使用addBackToStack函数相比,只存在三种状态的切换:onPauseonStop,onDestroyView。前者很好理解,因为addToBackStack函数顾名思义就是添加到回退栈中的意思,即当一个Fragment被另一个Fragment替换时会将之前的添加到回退栈中,因此也很好理解fragTwo的生命周期不受影响,因为是将被替换的添加到回退栈中,所以替换者不受影响。另外fragOne状态只到达onDestroyView,而无onDestroy,onDetach。这说明fragOne仅仅只是界面被销毁onDestroyView,而fragOne对象的实例依然被保存在FragmentManager中(因为无onDestroy,onDetach),它的部分状态依然被保存在FragmentManager中。我们可以来验证一下:
(2)我们点击按钮切换,让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的回退栈中。此时代码如下:
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
switch (v.getId()) {
case R.id.button1:
hideAllFrags(fragmentTransaction);
if (fragA == null) {
fragOne = new FragOne();
fragmentTransaction.add(R.id.frag_container, fragOne, fragNames[0]);
fragmentTransaction.addToBackStack(fragNames[0]);
} else {
fragmentTransaction.show(fragOne);
}
break;
case R.id.button2:
hideAllFrags(fragmentTransaction);
if (fragTwo == null) {
fragTwo = new FragTwo();
fragmentTransaction.add(R.id.frag_container, fragTwo, fragNames[1]);
fragmentTransaction.addToBackStack(fragNames[1]);
} else {
fragmentTransaction.show(fragTwo);
}
break;
default:
break;
}
fragmentTransaction.commit();
当我们使用add()/show()函数初次显示一个Fragment运行结果为:onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment处于运行状态。这个很好理解,不再赘述。
当我们点击按钮切换显示第二个Fragment时运行结果为:
可以看到此时fragOne无输出,表示fragOne的生命周期不受影响,而fragTwo的输出结果与直接初次显示fragTwo时是一样的。其实这也很好理解因为在add()/show()/hide()顾名思义就是添加显示隐藏的意思,它都不会对另外的Fragment的生命周期起作用。