?【聲明】
歡迎轉載,但請保留文章原始出處→_→
本文出處:[這里](http://www.cnblogs.com/smyhvae/p/3983234.html)
【正文】
上一章節中(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**的代碼如下:
~~~
~~~
<?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 package com.example.m01_fragmentlifecycle;
2
3 import android.app.Activity;
4 import android.app.Fragment;
5 import android.os.Bundle;
6 import android.util.Log;
7 import android.view.LayoutInflater;
8 import android.view.View;
9 import android.view.ViewGroup;
10
11 public class MyFragment extends Fragment {
12 private final String TAG = "MyFragment";
13
14 //獲得activity的傳遞的值
15 @Override
16 public void onAttach(Activity activity) {
17 // TODO Auto-generated method stub
18 super.onAttach(activity);
19 Log.i(TAG, "--MyFragment->>onAttach");
20 }
21
22 //實例化成員變量
23 @Override
24 public void onCreate(Bundle savedInstanceState) {
25 // TODO Auto-generated method stub
26 super.onCreate(savedInstanceState);
27 Log.i(TAG, "--MyFragment->>onCreate");
28 }
29
30 //給當前的fragment繪制UI布局,可以使用線程更新UI
31 @Override
32 public View onCreateView(LayoutInflater inflater, ViewGroup container,
33 Bundle savedInstanceState) {
34 Log.i(TAG, "--MyFragment->>onCreateView");
35 View view = inflater.inflate(R.layout.fragment01, null);
36 // TODO Auto-generated method stub
37 return view;
38 }
39
40 //表示activity執行oncreate方法完成了的時候會調用此方法
41 @Override
42 public void onActivityCreated(Bundle savedInstanceState) {
43 // TODO Auto-generated method stub
44 super.onActivityCreated(savedInstanceState);
45 Log.i(TAG, "--MyFragment->>onActivityCreated");
46 }
47
48 //和activity一致
49 @Override
50 public void onStart() {
51 // TODO Auto-generated method stub
52 super.onStart();
53 Log.i(TAG, "--MyFragment->>onStart");
54 }
55
56 //和activity一致
57 @Override
58 public void onResume() {
59 // TODO Auto-generated method stub
60 super.onResume();
61 Log.i(TAG, "--MyFragment->>onResume");
62 }
63
64 //和activity一致
65 @Override
66 public void onPause() {
67 // TODO Auto-generated method stub
68 super.onPause();
69 Log.i(TAG, "--MyFragment->>onPause");
70 }
71
72 //和activity一致
73 @Override
74 public void onStop() {
75 // TODO Auto-generated method stub
76 super.onStop();
77 Log.i(TAG, "--MyFragment->>onStop");
78 }
79
80 //表示fragment銷毀相關聯的UI布局
81 @Override
82 public void onDestroyView() {
83 // TODO Auto-generated method stub
84 super.onDestroyView();
85 Log.i(TAG, "--MyFragment->>onDestroyView");
86 }
87
88 //銷毀fragment對象
89 @Override
90 public void onDestroy() {
91 // TODO Auto-generated method stub
92 super.onDestroy();
93 Log.i(TAG, "--MyFragment->>onDestroy");
94 }
95
96 //脫離activity
97 @Override
98 public void onDetach() {
99 // TODO Auto-generated method stub
100 super.onDetach();
101 Log.i(TAG, "--MyFragment->>onDetach");
102 }
103 }
~~~
**activity_main.xml**的代碼如下:
~~~
<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 package com.example.m01_fragmentlifecycle;
2
3 import android.os.Bundle;
4 import android.app.Activity;
5 import android.app.FragmentManager;
6 import android.app.FragmentTransaction;
7 import android.util.Log;
8 import android.view.Menu;
9
10 public class MainActivity extends Activity {
11 private final String TAG = "MainActivity";
12 private FragmentManager manager;
13 private FragmentTransaction transaction;
14
15 @Override
16 protected void onCreate(Bundle savedInstanceState) {
17 super.onCreate(savedInstanceState);
18 setContentView(R.layout.activity_main);
19 manager = getFragmentManager();
20 transaction = manager.beginTransaction();
21 MyFragment fragment = new MyFragment();
22 transaction.add(R.id.line, fragment);
23 transaction.commit();
24 Log.i(TAG, "--MainActivity->>onCreate");
25 }
26
27 @Override
28 protected void onStart() {
29 // TODO Auto-generated method stub
30 super.onStart();
31 Log.i(TAG, "--MainActivity->>onStart");
32 }
33
34 @Override
35 protected void onResume() {
36 // TODO Auto-generated method stub
37 super.onResume();
38 Log.i(TAG, "--MainActivity->>onResume");
39 }
40
41 @Override
42 protected void onPause() {
43 // TODO Auto-generated method stub
44 super.onPause();
45 Log.i(TAG, "--MainActivity->>onPause");
46 }
47
48 @Override
49 protected void onStop() {
50 // TODO Auto-generated method stub
51 super.onStop();
52 Log.i(TAG, "--MainActivity->>onStop");
53 }
54
55 @Override
56 protected void onRestart() {
57 // TODO Auto-generated method stub
58 super.onRestart();
59 Log.i(TAG, "--MainActivity->>onRestart");
60 }
61 @Override
62 protected void onDestroy() {
63 // TODO Auto-generated method stub
64 super.onDestroy();
65 Log.i(TAG, "--MainActivity->>onDestroy");
66 }
67
68 @Override
69 public boolean onCreateOptionsMenu(Menu menu) {
70 // Inflate the menu; this adds items to the action bar if it is present.
71 getMenuInflater().inflate(R.menu.main, menu);
72 return true;
73 }
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行代碼)
~~~
1 //步驟一:添加一個FragmentTransaction的實例
2 FragmentManager fragmentManager =getFragmentManager();
3 FragmentTransaction transaction = fragmentManager.beginTransaction();
4 //步驟二:用add()方法加上Fragment的對象
5 RightFragment rightFragment = new RightFragment();
6 transaction.add(R.id.right, rightFragment);
7 transaction.addToBackStack(null);
8 //步驟三:調用commit()方法使得FragmentTransaction實例的改變生效
9 transaction.commit();
~~~
第07行代碼:我們在事務提交之前調用了FragmentTransaction的addToBackStack()方法,它可以接受一個名字用于描述返回棧的狀態,,一般傳入null即可。
【實例】**現在通過代碼來實現以下界面(下面的圖片為程序運行時加載的首頁),并且把每一個Fragment都加入到返回棧當中去,然后觀察其生命周期的變化。**完整代碼如下:

首先新建工程文件**m01_Fragment04**,然后開始我們的代碼之旅:
我們先把右側的四個Fragment建起來吧:
Fragment01.java主要部分的代碼如下:
~~~
1 package com.example.m01_fragment04;
2
3 import android.app.Fragment;
4 import android.os.Bundle;
5 import android.view.LayoutInflater;
6 import android.view.View;
7 import android.view.ViewGroup;
8
9 public class Fragment01 extends Fragment {
10
11 @Override
12 public void onCreate(Bundle savedInstanceState) {
13 super.onCreate(savedInstanceState);
14 }
15
16 @Override
17 public View onCreateView(LayoutInflater inflater, ViewGroup container,
18 Bundle savedInstanceState) {
19 View view = inflater.inflate(R.layout.f1, null);
20 return view;
21 }
22 @Override
23 public void onPause() {
24 super.onPause();
25 }
26 }
~~~
為避免啰嗦,這里就不把Fragment01生命周期中的其他函數羅列出來了,我們只要知道在實際代碼中這些函數都是加了的。
Fragment01的布局文件f1.xml的代碼如下:
~~~
<?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代碼如下:
~~~
<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 package com.example.m01_fragment04;
2
3 import android.os.Bundle;
4 import android.app.Activity;
5 import android.app.FragmentManager;
6 import android.app.FragmentTransaction;
7 import android.view.Menu;
8 import android.view.View;
9 import android.view.View.OnClickListener;
10 import android.widget.Button;
11
12 public class MainActivity extends Activity implements OnClickListener{
13
14 private FragmentManager manager;
15 private FragmentTransaction transaction;
16 private Button button1,button2,button3,button4;
17
18 @Override
19 protected void onCreate(Bundle savedInstanceState) {
20 super.onCreate(savedInstanceState);
21 setContentView(R.layout.activity_main);
22
23 manager = getFragmentManager();
24 button1 = (Button)this.findViewById(R.id.button1);
25 button1.setOnClickListener(this);
26 button2 = (Button)this.findViewById(R.id.button2);
27 button2.setOnClickListener(this);
28 button3 = (Button)this.findViewById(R.id.button3);
29 button3.setOnClickListener(this);
30 button4 = (Button)this.findViewById(R.id.button4);
31 button4.setOnClickListener(this);
32
33 }
34
35 @Override
36 public boolean onCreateOptionsMenu(Menu menu) {
37 // Inflate the menu; this adds items to the action bar if it is present.
38 getMenuInflater().inflate(R.menu.main, menu);
39 return true;
40 }
41
42 //通過點擊不同的按鈕,跳轉到不同的Fragment
43 @Override
44 public void onClick(View v) {
45 // TODO Auto-generated method stub
46 transaction = manager.beginTransaction();
47 switch (v.getId()) {
48 case R.id.button1:
49 Fragment01 fragment01 = new Fragment01();
50 transaction.replace(R.id.right, fragment01, "fragment01");
51 transaction.addToBackStack("fragment01");// 添加到Activity管理的回退棧中。
52 break;
53
54 case R.id.button2:
55 Fragment02 fragment02 = new Fragment02();
56 transaction.replace(R.id.right, fragment02, "fragment02");
57 transaction.addToBackStack("fragment02");// 添加到Activity管理的回退棧中。
58 break;
59
60 case R.id.button3:
61 Fragment03 fragment03 = new Fragment03();
62 transaction.replace(R.id.right, fragment03, "fragment03");
63 transaction.addToBackStack("fragment03");// 添加到Activity管理的回退棧中。
64 break;
65
66 case R.id.button4:
67 Fragment04 fragment04 = new Fragment04();
68 transaction.replace(R.id.right, fragment04, "fragment04");
69 transaction.addToBackStack("fragment04");// 添加到Activity管理的回退棧中。
70 break;
71 }
72 transaction.commit();
73 }
74
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