码迷,mamicode.com
首页 > 移动开发 > 详细

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

时间:2015-03-17 19:50:44      阅读:237      评论:0      收藏:0      [点我收藏+]

标签:

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!