Android系列之Fragment(二)Fragment的生命周期和返回栈

Android系列之Fragment(二)Fragment的生命周期和返回栈 - Android - 次元立方网 - 电脑知识与技术互动交流平台

【正文】

上一章节中(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的代码如下:

01. <?xml version='1.0' encoding='utf-8'?>
02. <LinearLayout xmlns:android='http://schemas.android.com/apk/res/android'
03.     android:layout_width='match_parent'
04.     android:layout_height='match_parent'
05.     android:orientation='vertical' >
06.  
07.     <RatingBar
08.         android:id='@+id/ratingBar1'
09.         android:layout_width='wrap_content'
10.         android:layout_height='wrap_content' />
11.  
12.     <Button
13.         android:id='@+id/button1'
14.         android:layout_width='wrap_content'
15.         android:layout_height='wrap_content'
16.         android:text='Button' />
17.  
18. </LinearLayout>

MyFragment.java代码如下:(注意生命周期中每个方法的作用)

001.   1 package com.example.m01_fragmentlifecycle;
002.   2
003.   3 import android.app.Activity;
004.   4 import android.app.Fragment;
005.   5 import android.os.Bundle;
006.   6 import android.util.Log;
007.   7 import android.view.LayoutInflater;
008.   8 import android.view.View;
009.   9 import android.view.ViewGroup;
010.  10
011.  11 public class MyFragment extends Fragment {
012.  12     private final String TAG = 'MyFragment';
013.  13    
014.  14     //获得activity的传递的值
015.  15     @Override
016.  16     public void onAttach(Activity activity) {
017.  17         // TODO Auto-generated method stub
018.  18         super.onAttach(activity);
019.  19         Log.i(TAG, '--MyFragment->>onAttach');
020.  20     }
021.  21
022.  22     //实例化成员变量
023.  23     @Override
024.  24     public void onCreate(Bundle savedInstanceState) {
025.  25         // TODO Auto-generated method stub
026.  26         super.onCreate(savedInstanceState);
027.  27         Log.i(TAG, '--MyFragment->>onCreate');
028.  28     }
029.  29
030.  30     //给当前的fragment绘制UI布局,可以使用线程更新UI
031.  31     @Override
032.  32     public View onCreateView(LayoutInflater inflater, ViewGroup container,
033.  33             Bundle savedInstanceState) {
034.  34         Log.i(TAG, '--MyFragment->>onCreateView');
035.  35         View view = inflater.inflate(R.layout.fragment01, null);
036.  36         // TODO Auto-generated method stub
037.  37         return view;
038.  38     }
039.  39
040.  40     //表示activity执行oncreate方法完成了的时候会调用此方法
041.  41     @Override
042.  42     public void onActivityCreated(Bundle savedInstanceState) {
043.  43         // TODO Auto-generated method stub
044.  44         super.onActivityCreated(savedInstanceState);
045.  45         Log.i(TAG, '--MyFragment->>onActivityCreated');
046.  46     }
047.  47
048.  48     //和activity一致
049.  49     @Override
050.  50     public void onStart() {
051.  51         // TODO Auto-generated method stub
052.  52         super.onStart();
053.  53         Log.i(TAG, '--MyFragment->>onStart');
054.  54     }
055.  55
056.  56     //和activity一致
057.  57     @Override
058.  58     public void onResume() {
059.  59         // TODO Auto-generated method stub
060.  60         super.onResume();
061.  61         Log.i(TAG, '--MyFragment->>onResume');
062.  62     }
063.  63
064.  64     //和activity一致
065.  65     @Override
066.  66     public void onPause() {
067.  67         // TODO Auto-generated method stub
068.  68         super.onPause();
069.  69         Log.i(TAG, '--MyFragment->>onPause');
070.  70     }
071.  71
072.  72     //和activity一致
073.  73     @Override
074.  74     public void onStop() {
075.  75         // TODO Auto-generated method stub
076.  76         super.onStop();
077.  77         Log.i(TAG, '--MyFragment->>onStop');
078.  78     }
079.  79
080.  80     //表示fragment销毁相关联的UI布局
081.  81     @Override
082.  82     public void onDestroyView() {
083.  83         // TODO Auto-generated method stub
084.  84         super.onDestroyView();
085.  85         Log.i(TAG, '--MyFragment->>onDestroyView');
086.  86     }
087.  87
088.  88     //销毁fragment对象
089.  89     @Override
090.  90     public void onDestroy() {
091.  91         // TODO Auto-generated method stub
092.  92         super.onDestroy();
093.  93         Log.i(TAG, '--MyFragment->>onDestroy');
094.  94     }
095.  95
096.  96     //脱离activity
097.  97     @Override
098.  98     public void onDetach() {
099.  99         // TODO Auto-generated method stub
100. 100         super.onDetach();
101. 101         Log.i(TAG, '--MyFragment->>onDetach');
102. 102     }
103. 103 }

activity_main.xml的代码如下:

01. <LinearLayout xmlns:android='http://schemas.android.com/apk/res/android'
02.     xmlns:tools='http://schemas.android.com/tools'
03.     android:layout_width='match_parent'
04.     android:layout_height='match_parent'
05.     android:orientation='horizontal'
06.     tools:context='.MainActivity' >
07.  
08.     <LinearLayout
09.         android:id='@+id/line'
10.         android:layout_width='wrap_content'
11.         android:layout_height='match_parent'
12.         android:orientation='vertical' >
13.     </LinearLayout>
14.      
15. </LinearLayout>

MainActivity.java的代码如下:

01. 1 package com.example.m01_fragmentlifecycle;
02.  2
03.  3 import android.os.Bundle;
04.  4 import android.app.Activity;
05.  5 import android.app.FragmentManager;
06.  6 import android.app.FragmentTransaction;
07.  7 import android.util.Log;
08.  8 import android.view.Menu;
09.  9
10. 10 public class MainActivity extends Activity {
11. 11     private final String TAG = 'MainActivity';
12. 12     private FragmentManager manager;
13. 13     private FragmentTransaction transaction;
14. 14
15. 15     @Override
16. 16     protected void onCreate(Bundle savedInstanceState) {
17. 17         super.onCreate(savedInstanceState);
18. 18         setContentView(R.layout.activity_main);
19. 19         manager = getFragmentManager();
20. 20         transaction = manager.beginTransaction();
21. 21         MyFragment fragment = new MyFragment();
22. 22         transaction.add(R.id.line, fragment);
23. 23         transaction.commit();
24. 24         Log.i(TAG, '--MainActivity->>onCreate');
25. 25     }
26. 26
27. 27     @Override
28. 28     protected void onStart() {
29. 29         // TODO Auto-generated method stub
30. 30         super.onStart();
31. 31         Log.i(TAG, '--MainActivity->>onStart');
32. 32     }
33. 33
34. 34     @Override
35. 35     protected void onResume() {
36. 36         // TODO Auto-generated method stub
37. 37         super.onResume();
38. 38         Log.i(TAG, '--MainActivity->>onResume');
39. 39     }
40. 40
41. 41     @Override
42. 42     protected void onPause() {
43. 43         // TODO Auto-generated method stub
44. 44         super.onPause();
45. 45         Log.i(TAG, '--MainActivity->>onPause');
46. 46     }
47. 47
48. 48     @Override
49. 49     protected void onStop() {
50. 50         // TODO Auto-generated method stub
51. 51         super.onStop();
52. 52         Log.i(TAG, '--MainActivity->>onStop');
53. 53     }
54. 54    
55. 55     @Override
56. 56     protected void onRestart() {
57. 57         // TODO Auto-generated method stub
58. 58         super.onRestart();
59. 59         Log.i(TAG, '--MainActivity->>onRestart');
60. 60     }
61. 61     @Override
62. 62     protected void onDestroy() {
63. 63         // TODO Auto-generated method stub
64. 64         super.onDestroy();
65. 65         Log.i(TAG, '--MainActivity->>onDestroy');
66. 66     }
67. 67
68. 68     @Override
69. 69     public boolean onCreateOptionsMenu(Menu menu) {
70. 70         // Inflate the menu; this adds items to the action bar if it is present.
71. 71         getMenuInflater().inflate(R.menu.main, menu);
72. 72         return true;
73. 73     }
74. 74 }

可以看到,上面的代码在每个生命周期的方法里都打印了日志,然后我们来运行一下程序,可以看到打印日志如下:

初次加载:(分成两部分来看)

\

\

点击一下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行代码)

01. 1                 //步骤一:添加一个FragmentTransaction的实例
02. 2                 FragmentManager fragmentManager =getFragmentManager();
03. 3                 FragmentTransaction transaction = fragmentManager.beginTransaction();
04. 4                 //步骤二:用add()方法加上Fragment的对象
05. 5                 RightFragment rightFragment = new RightFragment();
06. 6                 transaction.add(R.id.right, rightFragment);
07. <strong>7                 transaction.addToBackStack(null);
08. </strong>8                 //步骤三:调用commit()方法使得FragmentTransaction实例的改变生效
09. 9                 transaction.commit(); 

第07行代码:我们在事务提交之前调用了FragmentTransaction的addToBackStack()方法,它可以接受一个名字用于描述返回栈的状态,,一般传入null即可。

【实例】现在通过代码来实现以下界面(下面的图片为程序运行时加载的首页),并且把每一个Fragment都加入到返回栈当中去,然后观察其生命周期的变化。完整代码如下:

\

首先新建工程文件m01_Fragment04,然后开始我们的代码之旅:

我们先把右侧的四个Fragment建起来吧:

Fragment01.java主要部分的代码如下:

01. 1 package com.example.m01_fragment04;
02.  2
03.  3 import android.app.Fragment;
04.  4 import android.os.Bundle;
05.  5 import android.view.LayoutInflater;
06.  6 import android.view.View;
07.  7 import android.view.ViewGroup;
08.  8
09.  9 public class Fragment01 extends Fragment {
10. 10    
11. 11     @Override
12. 12     public void onCreate(Bundle savedInstanceState) {
13. 13         super.onCreate(savedInstanceState);
14. 14     }
15. 15    
16. 16     @Override
17. 17     public View onCreateView(LayoutInflater inflater, ViewGroup container,
18. 18             Bundle savedInstanceState) {
19. 19         View view = inflater.inflate(R.layout.f1, null);
20. 20         return view;
21. 21     }
22. 22     @Override
23. 23     public void onPause() {
24. 24         super.onPause();
25. 25     }
26. 26 }

为避免啰嗦,这里就不把Fragment01生命周期中的其他函数罗列出来了,我们只要知道在实际代码中这些函数都是加了的。

Fragment01的布局文件f1.xml的代码如下:

01. <?xml version='1.0' encoding='utf-8'?>
02. <LinearLayout xmlns:android='http://schemas.android.com/apk/res/android'
03.     android:layout_width='match_parent'
04.     android:layout_height='match_parent'
05.     android:orientation='vertical' >
06.  
07.     <TextView
08.         android:id='@+id/textView1'
09.         android:layout_width='wrap_content'
10.         android:layout_height='wrap_content'
11.         android:text='加载图片' />
12.  
13. </LinearLayout>

然后依次新建出Fragment02、Fragment03、Fragment04的java代码和布局文件。

MainActivity的布局文件activity_main.xml代码如下:

01. <LinearLayout xmlns:android='http://schemas.android.com/apk/res/android'
02.     xmlns:tools='http://schemas.android.com/tools'
03.     android:layout_width='match_parent'
04.     android:layout_height='match_parent'
05.     tools:context='.MainActivity' >
06.  
07.     <LinearLayout
08.         android:id='@+id/left'
09.         android:layout_width='wrap_content'
10.         android:layout_height='match_parent'
11.         android:background='#CCCCCC'
12.         android:orientation='vertical' >
13.  
14.         <Button
15.             android:id='@+id/button1'
16.             android:layout_width='wrap_content'
17.             android:layout_height='wrap_content'
18.             android:text='加载图片' />
19.  
20.         <Button
21.             android:id='@+id/button2'
22.             android:layout_width='wrap_content'
23.             android:layout_height='wrap_content'
24.             android:text='海报管理' />
25.  
26.         <Button
27.             android:id='@+id/button3'
28.             android:layout_width='wrap_content'
29.             android:layout_height='wrap_content'
30.             android:text='照片管理' />
31.     
32.         <Button
33.             android:id='@+id/button4'
34.             android:layout_width='wrap_content'
35.             android:layout_height='wrap_content'
36.             android:text='新闻管理' />       
37.          
38.     </LinearLayout>
39.  
40.     <LinearLayout
41.         android:id='@+id/right'      
42.         android:layout_width='0dp'
43.         android:layout_height='match_parent'
44.         android:layout_weight='1'
45.         android:orientation='vertical' >
46.     </LinearLayout>
47.  
48. </LinearLayout>

其中,第一个LinearLayout表示左侧的按钮,第二个LinearLayout留给右边的Fragment。

MainActivity.java的代码如下:

01. 1 package com.example.m01_fragment04;
02.  2
03.  3 import android.os.Bundle;
04.  4 import android.app.Activity;
05.  5 import android.app.FragmentManager;
06.  6 import android.app.FragmentTransaction;
07.  7 import android.view.Menu;
08.  8 import android.view.View;
09.  9 import android.view.View.OnClickListener;
10. 10 import android.widget.Button;
11. 11
12. 12 public class MainActivity extends Activity  implements OnClickListener{
13. 13
14. 14     private FragmentManager manager;
15. 15     private FragmentTransaction transaction;
16. 16     private Button button1,button2,button3,button4;
17. 17    
18. 18     @Override
19. 19     protected void onCreate(Bundle savedInstanceState) {
20. 20         super.onCreate(savedInstanceState);
21. 21         setContentView(R.layout.activity_main);
22. 22        
23. 23     manager = getFragmentManager();
24. 24         button1 = (Button)this.findViewById(R.id.button1);
25. 25         button1.setOnClickListener(this);
26. 26         button2 = (Button)this.findViewById(R.id.button2);
27. 27         button2.setOnClickListener(this);
28. 28         button3 = (Button)this.findViewById(R.id.button3);
29. 29         button3.setOnClickListener(this);
30. 30         button4 = (Button)this.findViewById(R.id.button4);
31. 31         button4.setOnClickListener(this);
32. 32        
33. 33     }
34. 34
35. 35     @Override
36. 36     public boolean onCreateOptionsMenu(Menu menu) {
37. 37         // Inflate the menu; this adds items to the action bar if it is present.
38. 38         getMenuInflater().inflate(R.menu.main, menu);
39. 39         return true;
40. 40     }
41. 41
42. 42     //通过点击不同的按钮,跳转到不同的Fragment
43. 43     @Override
44. 44     public void onClick(View v) {
45. 45         // TODO Auto-generated method stub
46. <strong>46         transaction = manager.beginTransaction();
47. </strong>47         switch (v.getId()) {
48. 48         case R.id.button1:
49. 49             Fragment01 fragment01 = new Fragment01();
50. 50             transaction.replace(R.id.right, fragment01, 'fragment01');
51. 51             transaction.addToBackStack('fragment01');// 添加到Activity管理的回退栈中。
52. 52             break;
53. 53
54. 54         case R.id.button2:
55. 55             Fragment02 fragment02 = new Fragment02();
56. 56             transaction.replace(R.id.right, fragment02, 'fragment02');
57. 57             transaction.addToBackStack('fragment02');// 添加到Activity管理的回退栈中。
58. 58             break;
59. 59
60. 60         case R.id.button3:
61. 61             Fragment03 fragment03 = new Fragment03();
62. 62             transaction.replace(R.id.right, fragment03, 'fragment03');
63. 63             transaction.addToBackStack('fragment03');// 添加到Activity管理的回退栈中。
64. 64             break;
65. 65
66. 66         case R.id.button4:
67. 67             Fragment04 fragment04 = new Fragment04();
68. 68             transaction.replace(R.id.right, fragment04, 'fragment04');
69. 69             transaction.addToBackStack('fragment04');// 添加到Activity管理的回退栈中。
70. 70             break;
71. 71         }
72. <strong>72 </strong><strong>        transaction.commit();   </strong>    
73. 73     }
74. 74    
75. 75 }

上当代码中,通过点击不同的按钮,就能跳到对应的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/p/3983234.html

转载于:https://www.cnblogs.com/seven1979/p/4345126.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值