【android】關於FragmentManager動態管理Fragment時Fragment生命週期的探究
Fragment是Android中的重要元件,在Android 3.0的時候新增進來。
關於Fragment的生命週期,我相信瞭解過的開發人員都應該把以下方法脫口而出:onAttach, onCreate, onCreateView, onViewCreated, onActivityCreated, onStart, onResume, onPause, onStop, onDestroyView, onDestroy, onDetach.
當Fragment以靜態的方式,即通過在佈局檔案中以其它控制元件的方式設定時,它的生命週期隨所在Activity的生命週期而發生變化。此時其生命週期的方法呼叫過程是這樣的:
1,當首次展示佈局頁面時,其生命週期方法呼叫的順序是:
2,而當關閉手機螢幕或者手機螢幕變暗時,其其生命週期方法呼叫的順序是:
3,當再次對手機螢幕解鎖或者手機螢幕變亮時,其生命週期方法呼叫的順序是:
4,而當對當前Fragment所在螢幕按返回鍵時,其生命週期方法呼叫的順序是:
1 01-13 17:08:46.959 3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onPause 2 01-13 17:08:46.959 3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onStopView Code3 01-13 17:08:46.959 3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onDestroyView 4 01-13 17:08:46.959 3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onDestroy 5 01-13 17:08:46.959 3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onDetach
但是當使用FragmentManager動態的管理Fragment並且涉及到是否addToBackStack時,其生命週期的展現就略微顯得有些複雜了。但是還沒有複雜到無法理解。
好,下面,我們就探究一下這些問題。
首先,我們重寫了兩個Fragment,主要是重寫了它們的生命週期方法,通過在其生命週期方法中打印出Log的方式來顯示其方法的呼叫。
兩個類分別是:
1 package com.yeepay.fraglifecircletest.frag;
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 import com.yeepay.fraglifecircletest.R;
12
13 public class FragA extends Fragment {14 private static final String TAG = FragA.class.getSimpleName();
15
16 @Override
17 public void onAttach(Activity activity) {
18 super.onAttach(activity);
19 Log.i(TAG, "onAttach");
20 }
21
22 @Override
23 public void onCreate(Bundle savedInstanceState) {
24 super.onCreate(savedInstanceState);
25 Log.i(TAG, "onCreate");
26 }
27
28 @Override
29 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
30 Log.i(TAG, "onCreateView");
31 return inflater.inflate(R.layout.fragment_test_a, null, false);
32 }
33
34 @Override
35 public void onViewCreated(View view, Bundle savedInstanceState) {
36 Log.i(TAG, "onViewCreated");
37 super.onViewCreated(view, savedInstanceState);
38 }
39
40 @Override
41 public void onDestroy() {
42 Log.i(TAG, "onDestroy");
43 super.onDestroy();
44 }
45
46 @Override
47 public void onDetach() {
48 Log.i(TAG, "onDetach");
49 super.onDetach();
50 }
51
52 @Override
53 public void onDestroyView() {
54 Log.i(TAG, "onDestroyView");
55 super.onDestroyView();
56 }
57
58 @Override
59 public void onStart() {
60 Log.i(TAG, "onStart");
61 super.onStart();
62 }
63
64 @Override
65 public void onStop() {
66 Log.i(TAG, "onStop");
67 super.onStop();
68 }
69
70 @Override
71 public void onResume() {
72 Log.i(TAG, "onResume");
73 super.onResume();
74 }
75
76 @Override
77 public void onPause() {
78 Log.i(TAG, "onPause");
79 super.onPause();
80 }
81
82 @Override
83 public void onActivityCreated(Bundle savedInstanceState) {
84 Log.i(TAG, "onActivityCreated");
85 super.onActivityCreated(savedInstanceState);
86 }
87 }
FragA.java
1 package com.yeepay.fraglifecircletest.frag;
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 import com.yeepay.fraglifecircletest.R;
12
13 public class FragB extends Fragment {14 private static final String TAG = FragB.class.getSimpleName();
15
16 @Override
17 public void onAttach(Activity activity) {
18 super.onAttach(activity);
19 Log.i(TAG, "onAttach");
20 }
21
22 @Override
23 public void onCreate(Bundle savedInstanceState) {
24 super.onCreate(savedInstanceState);
25 Log.i(TAG, "onCreate");
26 }
27
28 @Override
29 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
30 Log.i(TAG, "onCreateView");
31 return inflater.inflate(R.layout.fragment_test_b, null, false);
32 }
33
34 @Override
35 public void onViewCreated(View view, Bundle savedInstanceState) {
36 Log.i(TAG, "onViewCreated");
37 super.onViewCreated(view, savedInstanceState);
38 }
39
40 @Override
41 public void onDestroy() {
42 Log.i(TAG, "onDestroy");
43 super.onDestroy();
44 }
45
46 @Override
47 public void onDetach() {
48 Log.i(TAG, "onDetach");
49 super.onDetach();
50 }
51
52 @Override
53 public void onDestroyView() {
54 Log.i(TAG, "onDestroyView");
55 super.onDestroyView();
56 }
57
58 @Override
59 public void onStart() {
60 Log.i(TAG, "onStart");
61 super.onStart();
62 }
63
64 @Override
65 public void onStop() {
66 Log.i(TAG, "onStop");
67 super.onStop();
68 }
69
70 @Override
71 public void onResume() {
72 Log.i(TAG, "onResume");
73 super.onResume();
74 }
75
76 @Override
77 public void onPause() {
78 Log.i(TAG, "onPause");
79 super.onPause();
80 }
81
82 @Override
83 public void onActivityCreated(Bundle savedInstanceState) {
84 Log.i(TAG, "onActivityCreated");
85 super.onActivityCreated(savedInstanceState);
86 }
87 }
FragB.java
1,當我們通過以下方式新增FragA時,
1 FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
2 fragA = new FragA();
3 fragmentTransaction.replace(R.id.frag_container, fragA, fragNames[0]);4 fragmentTransaction.commit();
View Code
它的生命週期展示方式是同在佈局檔案中靜態設定的表現一模一樣的,這裡不再詳細展開,大家可以檢視一下以上內容。
2,當我們以如下方式展示FragA並且沒有addToBackStack時,
1 @Override
2 public void onClick(View v) {
3 FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
4 switch (v.getId()) {
5 case R.id.button1:
6 if (fragA == null) {
7 fragA = new FragA();
8 fragmentTransaction.replace(R.id.frag_container, fragA, fragNames[0]);
9 // fragmentTransaction.addToBackStack(fragNames[0]);
10 } else {
11 Fragment fragment = fragmentManager.findFragmentByTag(fragNames[0]);
12 fragmentTransaction.replace(R.id.frag_container, fragment, fragNames[0]);
13 }
14 break;
15 case R.id.button2:
16 if (fragB == null) {
17 fragB = new FragB();
18 fragmentTransaction.replace(R.id.frag_container, fragB, fragNames[1]);
19 // fragmentTransaction.addToBackStack(fragNames[1]);
20 } else {
21 Fragment fragment = fragmentManager.findFragmentByTag(fragNames[1]);
22 fragmentTransaction.replace(R.id.frag_container, fragment, fragNames[1]);
23 }
24 break;
25 default:
26 break;
27 }
28 fragmentTransaction.commit();
29 }
View Code
FragA生命週期呼叫順序是:
此時,如果再點選另外一個按鈕B,將FragB展示出來,FragA和FragB的生命週期展示方式是:
可以看到,FragA呼叫順序為onPause, onStop, onDestroyView, onDestroy, onDetach.這說明,FragA已經被FragmentManager完全拋棄了,取而代之的是FragB的完全展現。而如果此時按返回鍵的話,FragB的生命週期也將是onPause, onStop, onDestroyView, onDestroy, onDetach。這說明,在新增Fragment時如果沒有呼叫addToBackStack方式的話,當FragmentManager更換Fragment時,是不儲存Fragment的狀態的。
3,下面我們在替換Fragment時順便addToBackStack,則其生命週期展現方式是:
1 replace FragA and addToBackStack
2 ########################################################################################
3 01-13 17:08:43.359 3102-3102/com.yeepay.fraglifecircletest I/FragA﹕ onAttach
4 01-13 17:08:43.359