上一章节中(Android系列之Fragment(一)—-Fragment加载到Activity当中),我们对Fragment的生命周期进行了简单介绍,这一章节将对生命周期和返回栈进行详细介绍。
一、Fragment的生命周期初探: 因为Fragment必须嵌入在Acitivity中使用,所以Fragment的生命周期和它所在的Activity是密切相关的。
如果Activity是暂停状态,其中所有的Fragment都是暂停状态;如果Activity是stopped状态,这个Activity中所有的Fragment都不能被启动;如果Activity被销毁,那么它其中的所有Fragment都会被销毁。
但是,当Activity在活动状态,可以独立控制Fragment的状态,比如加上或者移除Fragment。
当这样进行fragment transaction(转换)的时候,可以把fragment放入Activity的back stack中,这样用户就可以进行返回操作。
使用Fragment时,需要继承Fragment或者Fragment的子类(DialogFragment, ListFragment, PreferenceFragment, WebViewFragment),所以Fragment的代码看起来和Activity的类似。
每当创建一个Fragment时,首先添加以下三个回调方法:
onCreate():系统在创建Fragment的时候调用这个方法,这里应该初始化相关的组件,一些即便是被暂停或者被停止时依然需要保留的东西。 onCreateView():当第一次绘制Fragment的UI时系统调用这个方法,该方法将返回一个View,如果Fragment不提供UI也可以返回null。注意,如果继承自ListFragment,onCreateView()默认的实现会返回一个ListView,所以不用自己实现。
onPause():当用户离开Fragment时第一个调用这个方法,需要提交一些变化,因为用户很可能不再返回来。
将Fragment加载到Activity当中有两种方式:
方式一:添加Fragment到Activity的布局文件当中 方式二:在Activity的代码中动态添加Fragment(荐)
第一种方式虽然简单但灵活性不够。添加Fragment到Activity的布局文件当中,就等同于将Fragment及其视图与activity的视图绑定在一起,且在activity的生命周期过程中,无法切换fragment视图。
第二种方式比较复杂,但也是唯一一种可以在运行时控制fragment的方式(加载、移除、替换)。
二、Fragment的生命周期详解: 先来看一下官方文档的图片吧:
我们再把Activity的生命周期和Fragment的生命周期对比一下,就清楚很多了: 我们还是在实例中来看一下Fragment的生命周期吧。
【实例】在MainActivity中加载一个Fragment:(完整版代码如下)
我们所创建的Fragment的布局文件fragment01.xml的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?xml version="1.0" encoding="utf-8" ?> <LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:layout_width ="match_parent" android:layout_height ="match_parent" android:orientation ="vertical" > <RatingBar android:id ="@+id/ratingBar1" android:layout_width ="wrap_content" android:layout_height ="wrap_content" /> <Button android:id ="@+id/button1" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:text ="Button" /> </LinearLayout >
MyFragment.java代码如下:(注意生命周期中每个方法的作用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 package com.example .m01_fragmentlifecycle ; 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 MyFragment extends Fragment { private final String TAG = "MyFragment" ; @Override public void onAttach (Activity activity ) { super .onAttach (activity); Log .i (TAG , "--MyFragment->>onAttach" ); } @Override public void onCreate (Bundle savedInstanceState ) { super .onCreate (savedInstanceState); Log .i (TAG , "--MyFragment->>onCreate" ); } @Override public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) { Log .i (TAG , "--MyFragment->>onCreateView" ); View view = inflater.inflate (R.layout .fragment01 , null ); return view; } @Override public void onActivityCreated (Bundle savedInstanceState ) { super .onActivityCreated (savedInstanceState); Log .i (TAG , "--MyFragment->>onActivityCreated" ); } @Override public void onStart ( ) { super .onStart (); Log .i (TAG , "--MyFragment->>onStart" ); } @Override public void onResume ( ) { super .onResume (); Log .i (TAG , "--MyFragment->>onResume" ); } @Override public void onPause ( ) { super .onPause (); Log .i (TAG , "--MyFragment->>onPause" ); } @Override public void onStop ( ) { super .onStop (); Log .i (TAG , "--MyFragment->>onStop" ); } @Override public void onDestroyView ( ) { super .onDestroyView (); Log .i (TAG , "--MyFragment->>onDestroyView" ); } @Override public void onDestroy ( ) { super .onDestroy (); Log .i (TAG , "--MyFragment->>onDestroy" ); } @Override public void onDetach ( ) { super .onDetach (); Log .i (TAG , "--MyFragment->>onDetach" ); } }
activity_main.xml的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android" xmlns:tools ="http://schemas.android.com/tools" android:layout_width ="match_parent" android:layout_height ="match_parent" android:orientation ="horizontal" tools:context =".MainActivity" > <LinearLayout android:id ="@+id/line" android:layout_width ="wrap_content" android:layout_height ="match_parent" android:orientation ="vertical" > </LinearLayout > </LinearLayout >
MainActivity.java的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 package com.example .m01_fragmentlifecycle ; import android.os .Bundle ;import android.app .Activity ;import android.app .FragmentManager ;import android.app .FragmentTransaction ;import android.util .Log ;import android.view .Menu ;public class MainActivity extends Activity { private final String TAG = "MainActivity" ; private FragmentManager manager; private FragmentTransaction transaction; @Override protected void onCreate (Bundle savedInstanceState ) { super .onCreate (savedInstanceState); setContentView (R.layout .activity_main ); manager = getFragmentManager (); transaction = manager.beginTransaction (); MyFragment fragment = new MyFragment (); transaction.add (R.id .line , fragment); transaction.commit (); Log .i (TAG , "--MainActivity->>onCreate" ); } @Override protected void onStart ( ) { super .onStart (); Log .i (TAG , "--MainActivity->>onStart" ); } @Override protected void onResume ( ) { super .onResume (); Log .i (TAG , "--MainActivity->>onResume" ); } @Override protected void onPause ( ) { super .onPause (); Log .i (TAG , "--MainActivity->>onPause" ); } @Override protected void onStop ( ) { super .onStop (); Log .i (TAG , "--MainActivity->>onStop" ); } @Override protected void onRestart ( ) { super .onRestart (); Log .i (TAG , "--MainActivity->>onRestart" ); } @Override protected void onDestroy ( ) { super .onDestroy (); Log .i (TAG , "--MainActivity->>onDestroy" ); } @Override public boolean onCreateOptionsMenu (Menu menu ) { getMenuInflater ().inflate (R.menu .main , menu); return true ; } }
可以看到,上面的代码在每个生命周期的方法里都打印了日志,然后我们来运行一下程序,可以看到打印日志如下:
初次加载:(分成两部分来看)
点击一下home键(或接入电话),打印日志如下: 重新进入进入程序(或电话结束),打印日志如下: 点击back键退出程序,打印日志如下: 通过上面的日志,我们能够看出,Fragment和Activity的生命周期太相似了。只是有几个Activity中没有的新方法,需要重点介绍一下:
onAttach方法:Fragment和Activity建立关联的时候调用(获得activity的传递的值) onCreateView方法:为Fragment创建视图(加载布局)时调用(给当前的fragment绘制UI布局,可以使用线程更新UI) onActivityCreated方法:当Activity中的onCreate方法执行完后调用(表示activity执行oncreate方法完成了的时候会调用此方法) onDestroyView方法:Fragment中的布局被移除时调用(表示fragment销毁相关联的UI布局) onDetach方法:Fragment和Activity解除关联的时候调用(脱离activity)
三、Fragment返回栈的管理: 将Fragment添加到返回栈中:
假设现在我们有两个Fragment:Fragment01和Fragment02,我们现在从Fragment01的界面跳到Fragment02,然后按Back键,发现程序是直接退出了,而不是返回到Fragment01。如果现在想实现以下功能:从Fragment01的界面跳到Fragment02,然后按Back键,会返回到Fragment01。这个功能该怎么实现呢?这其实就利用到了返回栈的知识。
其实很简单,FragmentTransaction中提供了一个addToBackStack()方法,可以将一个事务添加到返回栈中。
我们先回顾一下之前动态加载Fragment的代码,然后在此基础之上,增加一行代码就可以将Fragment添加到返回栈中:(即第07行代码)
1 2 3 4 5 6 7 8 9 FragmentManager fragmentManager =getFragmentManager() ; FragmentTransaction transaction = fragmentManager.begin Transaction() ; RightFragment rightFragment = new RightFragment() ; transaction.add(R . id.right, rightFragment); transaction.addToBackStack(null ) ; transaction.commit() ;
第07行代码:我们在事务提交之前调用了FragmentTransaction的addToBackStack()方法,它可以接受一个名字用于描述返回栈的状态,一般传入null即可。
【实例】现在通过代码来实现以下界面(下面的图片为程序运行时加载的首页),并且把每一个Fragment都加入到返回栈当中去,然后观察其生命周期的变化。完整代码如下: 首先新建工程文件m01_Fragment04,然后开始我们的代码之旅:
我们先把右侧的四个Fragment建起来吧:
Fragment01.java主要部分的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.example.m01_fragment04;import android.app.Fragment;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;public class Fragment01 extends Fragment { @Override public void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); } @Override public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.f1, null ); return view; } @Override public void onPause () { super .onPause(); } }
为避免啰嗦,这里就不把Fragment01生命周期中的其他函数罗列出来了,我们只要知道在实际代码中这些函数都是加了的。
Fragment01的布局文件f1.xml的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 <?xml version="1.0" encoding="utf-8" ?> <LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:layout_width ="match_parent" android:layout_height ="match_parent" android:orientation ="vertical" > <TextView android:id ="@+id/textView1" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:text ="加载图片" /> </LinearLayout >
然后依次新建出Fragment02、Fragment03、Fragment04的java代码和布局文件。
MainActivity的布局文件activity_main.xml代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <LinearLayout android:id ="@+id/left" android:layout_width="wrap_content" android:layout_height="match_parent" android:background="#CCCCCC" android:orientation="vertical" > <Button android:id ="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text ="加载图片" /> <Button android:id ="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text ="海报管理" /> <Button android:id ="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text ="照片管理" /> <Button android:id ="@+id/button4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text ="新闻管理" /> </LinearLayout> <LinearLayout android:id ="@+id/right" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical" > </LinearLayout> </LinearLayout>
其中,第一个LinearLayout表示左侧的按钮,第二个LinearLayout留给右边的Fragment。
MainActivity.java的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 package com.example.m01_fragment04; import android.os.Bundle; import android.app.Activity; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity implements OnClickListener{ private FragmentManager manager; private FragmentTransaction transaction; private Button button1,button2,button3,button4; @Override protected void onCreate(Bundle savedInstanceState ) { super.onCreate(savedInstanceState ) ; setContentView(R.layout .activity_main ) ; manager = getFragmentManager() ; button1 = (Button)this.findViewById(R.id .button1 ) ; button1.setOnClickListener(this ) ; button2 = (Button)this.findViewById(R.id .button2 ) ; button2.setOnClickListener(this ) ; button3 = (Button)this.findViewById(R.id .button3 ) ; button3.setOnClickListener(this ) ; button4 = (Button)this.findViewById(R.id .button4 ) ; button4.setOnClickListener(this ) ; } @Override public boolean onCreateOptionsMenu(Menu menu ) { getMenuInflater() .inflate(R . menu.main, menu); return true ; } @Override public void onClick(View v ) { transaction = manager.begin Transaction() ; switch (v.getId() ) { case R . id.button1: Fragment01 fragment01 = new Fragment01() ; transaction.replace(R . id.right, fragment01, "fragment01" ); transaction.addToBackStack("fragment01" ) ; break; case R . id.button2: Fragment02 fragment02 = new Fragment02() ; transaction.replace(R . id.right, fragment02, "fragment02" ); transaction.addToBackStack("fragment02" ) ; break; case R . id.button3: Fragment03 fragment03 = new Fragment03() ; transaction.replace(R . id.right, fragment03, "fragment03" ); transaction.addToBackStack("fragment03" ) ; break; case R . id.button4: Fragment04 fragment04 = new Fragment04() ; transaction.replace(R . id.right, fragment04, "fragment04" ); transaction.addToBackStack("fragment04" ) ; break; } transaction.commit() ; } }
上当代码中,通过点击不同的按钮,就能跳到对应的Fragment,而这四个Fragment都已经加入到了返回栈当中。运行程序之后,也是这样的。
注意第46行和第72行,transaction = manager.beginTransaction()意味着开始,transaction.commit()意味着结束。
我们就其中的fragment01和fragment02来讨论一下他们的生命周期的变化:
运行程序后,界面如下,没有任何fragment被加载: 点击左侧第一个按钮,加载fragment01: 点击左侧第二个按钮,加载fragment02(此时fragment01被替换,并被压到了栈当中): 注:如果fragment01在替换的时候没有被压到栈中,那就会被销毁,在执行完onDestroyView()方法后,会继续执行onDestroy()和onDetach()方法。
按Back键,fragment01重新返回到屏幕:(fragment02被销毁) 再按Back键,fragment01被销毁: 注:Fragment的返回栈由Activity管理;而Activity的返回栈由系统管理。
【工程文件】
链接:http://pan.baidu.com/s/1i3DrYmx
密码:uh46
【声明】
欢迎转载,但请保留文章原始出处→_→
生命壹号:http://www.cnblogs.com/smyhvae/
文章来源:http://www.cnblogs.com/smyhvae/p/3983234.html
联系方式:smyhvae@163.com