标签:
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
Android系列之Fragment(二)Fragment的生命周期和返回栈
标签:
原文地址:http://www.cnblogs.com/seven1979/p/4345126.html