标签:
在Android 3.0中,Fragment作为一个重要的组件,被添加进来,这个类在 android.app.Fragment; 中,可以直接继承Fragment 创建一个Fragment类,
当然Fragment也是可以在低版本中兼容,在android-support-v4.jar中包含一个FragmentActivity. 可以直接继承FragmentActivity来创建一个Fragment类。
Fragment主要用于平板中,例如:左边显示列表项目,右边显示明细项目,当用户点击每一个条目的时候,右边的Fragment就直接显示用户点击项的明细。
如下图所示:
Fragment的生命周期有:
onAttach(); onCreat(); onCreateView(); onViewCreated(); onActivityCreated(); onStart(); onResume(); onPause(); onStop(); onDestroyView(); onDestroy(); onDetach();
下面请看安卓的官方文档图片:
Fragment的生命周期和Activity的生命周期是有很大关系的. 在含有Fragment 的 Activity的生命周期的变化中,包含着Fragment生命周期的变化
下面请看Android官方文档的Activity与Fragment的生命周期的比较:
当Fragment以静态的方式,即通过在布局文件中以其它控件的方式设置时,它的生命周期随所在Activity的生命周期而发生变化。此时其生命周期的方法调用过程是这样的
1、当Fragment所在的布局页面首次出现的时候, Fragment的生命周期是这样调用的:
2、当手机屏幕关闭或者手机屏幕变暗时,Fragment的生命周期是这样调用的:
3、当进行完上面 2 的操作。再对手机屏幕打开,或者手机变亮的时候,调用顺序是:
4、当对当前的Fragment所在的屏幕按下返回键时,调用顺序是:
但是,当使用FragmentManager管理Fragment并且涉及到addToBackStack的时候,那么它的生命周期就会变得更加复杂一点。
下面就来探讨一下这个问题:
先定义FragA.java文件和FragB.java文件 如下:
package com.example.my; import java.util.jar.Attributes.Name; 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; public class FragA extends Fragment { public static String TAG = FragA.class.getSimpleName(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i(TAG, "onCreate"); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Log.i(TAG, "onActivityCreated"); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.i(TAG, "onCreateView"); return super.onCreateView(inflater, container, savedInstanceState); } @Override public void onAttach(Activity activity) { super.onAttach(activity); Log.i(TAG, "onAttach"); } @Override public void onDestroy() { Log.i(TAG, "onDestory"); super.onDestroy(); } @Override public void onDetach() { Log.i(TAG, "onDetch"); super.onDetach(); } @Override public void onPause() { Log.i(TAG, "onPause"); super.onPause(); } @Override public void onDestroyView() { super.onDestroyView(); Log.i(TAG, "onDestroyView"); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); Log.i(TAG, "onViewCreated"); } @Override public void onStart() { super.onStart(); Log.i(TAG, "onStart"); } }
FragB.java文件:
package com.example.my; import java.util.jar.Attributes.Name; 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; public class FragB extends Fragment { public static String TAG = FragB.class.getSimpleName(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i(TAG, "onCreate"); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Log.i(TAG, "onActivityCreated"); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.i(TAG, "onCreateView"); return super.onCreateView(inflater, container, savedInstanceState); } @Override public void onAttach(Activity activity) { super.onAttach(activity); Log.i(TAG, "onAttach"); } @Override public void onDestroy() { Log.i(TAG, "onDestory"); super.onDestroy(); } @Override public void onDetach() { Log.i(TAG, "onDetch"); super.onDetach(); } @Override public void onPause() { Log.i(TAG, "onPause"); super.onPause(); } @Override public void onDestroyView() { super.onDestroyView(); Log.i(TAG, "onDestroyView"); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); Log.i(TAG, "onViewCreated"); } @Override public void onStart() { super.onStart(); Log.i(TAG, "onStart"); } }
1、当以下面的方式添加FragA时:
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragA = new FragA(); fragmentTransaction.replace(R.id.frag_container, fragA, null); 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]);<pre class="java" name="code"> } break; default: break; } fragmentTransaction.commit(); }
FragA生命周期调用顺序是:
如果再点击另外一个按钮,将FragB展示出来,请看下面的FragA和FragB的生命周期调用:
我们从这里可以看到。FragA调用顺序为 onPause() , onStop(), onDestoryView(), onDetach() ,这说明, FragA已经被FragmentManager处理掉了,取而代之的是FragB的展现,如果我们也按下返回键按钮,那么FragB的生命周期也是一样的调用onPause() , onStop(), onDestoryView(), onDetach()。这个说明,在添加Fragment时如果没有调用addToBackStack()方式的话,当FragmentManager要更换Fragment的时候,是不会保存要被更换的Fragment的状态的。
3、下面我们在替换Fragment的时候,添加addToBackStack(),那么它的生命周期会是什么样的呢?如下图的:
由此看出,调用addToBackStack()和没调用是有区别的。 当通过按钮,使FragB来替换FragA的时候,此时FragB和FragA的生命周期会做出什么样的变化呢?请看下面的图片:
所以可以看出,FragA生命周期方法只是调用到了onDestroyView,而onDestroy和onDetach则没有被调用,这说明FragA的界面已经被销毁了,但是FragmentManager并没有完全销毁FragA,FragA依然有状态保存在FragmentManager里面。
然后再点击按钮A,使用FragA来替换当前显示的FragB,此时FragA和FragB的生命周期方法调用顺序为:
可以看到,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的调用顺序为:
可以看出没有什么不同于以上所言的部分。然后,点击按钮B时,FragA和FragB的调用顺序为:
可以看出,FragA并没有调用生命周期方法,这说明是展示FragB时,FragA的生命周期并没有发生变化。而FragB的生命周期与初次点击按钮A时FragA的生命周期方法相同。
然后再继续点击按钮A和B,此时打印出来的log为:
这说明在FragA和FragB添加进BackStack之后无论如何地show或者hide,它们的生命周期不再发生变化。
而当屏幕上锁或变暗,然后再解锁或者变亮时,FragA和FragB的生命周期方法调用顺序为:
可以看得出来,两个Fragment都调用了onPause, onStop, onStart, onResume。而且FragA的调用要在FragB之前,这说明跟他们添加进BackStack的顺序有关。
本文参考了一些经典资料而出,有不足之处还望谅解,指正。
标签:
原文地址:http://blog.csdn.net/wccchangchun/article/details/51203640