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.????<RatingBar08.????????android:id=‘@+id/ratingBar1‘09.????????android:layout_width=‘wrap_content‘10.????????android:layout_height=‘wrap_content‘/>11.?12.????<Button13.????????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.??1packagecom.example.m01_fragmentlifecycle;002.??2003.??3importandroid.app.Activity;004.??4importandroid.app.Fragment;005.??5importandroid.os.Bundle;006.??6importandroid.util.Log;007.??7importandroid.view.LayoutInflater;008.??8importandroid.view.View;009.??9importandroid.view.ViewGroup;010.?10011.?11publicclassMyFragmentextendsFragment {012.?12????privatefinalString TAG =‘MyFragment‘;013.?13????014.?14????//获得activity的传递的值015.?15????@Override016.?16????publicvoidonAttach(Activity activity) {017.?17????????// TODO Auto-generated method stub018.?18????????super.onAttach(activity);019.?19????????Log.i(TAG,‘--MyFragment->>onAttach‘);020.?20????}021.?21022.?22????//实例化成员变量023.?23????@Override024.?24????publicvoidonCreate(Bundle savedInstanceState) {025.?25????????// TODO Auto-generated method stub026.?26????????super.onCreate(savedInstanceState);027.?27????????Log.i(TAG,‘--MyFragment->>onCreate‘);028.?28????}029.?29030.?30????//给当前的fragment绘制UI布局,可以使用线程更新UI031.?31????@Override032.?32????publicView 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 stub037.?37????????returnview;038.?38????}039.?39040.?40????//表示activity执行oncreate方法完成了的时候会调用此方法041.?41????@Override042.?42????publicvoidonActivityCreated(Bundle savedInstanceState) {043.?43????????// TODO Auto-generated method stub044.?44????????super.onActivityCreated(savedInstanceState);045.?45????????Log.i(TAG,‘--MyFragment->>onActivityCreated‘);046.?46????}047.?47048.?48????//和activity一致049.?49????@Override050.?50????publicvoidonStart() {051.?51????????// TODO Auto-generated method stub052.?52????????super.onStart();053.?53????????Log.i(TAG,‘--MyFragment->>onStart‘);054.?54????}055.?55056.?56????//和activity一致057.?57????@Override058.?58????publicvoidonResume() {059.?59????????// TODO Auto-generated method stub060.?60????????super.onResume();061.?61????????Log.i(TAG,‘--MyFragment->>onResume‘);062.?62????}063.?63064.?64????//和activity一致065.?65????@Override066.?66????publicvoidonPause() {067.?67????????// TODO Auto-generated method stub068.?68????????super.onPause();069.?69????????Log.i(TAG,‘--MyFragment->>onPause‘);070.?70????}071.?71072.?72????//和activity一致073.?73????@Override074.?74????publicvoidonStop() {075.?75????????// TODO Auto-generated method stub076.?76????????super.onStop();077.?77????????Log.i(TAG,‘--MyFragment->>onStop‘);078.?78????}079.?79080.?80????//表示fragment销毁相关联的UI布局081.?81????@Override082.?82????publicvoidonDestroyView() {083.?83????????// TODO Auto-generated method stub084.?84????????super.onDestroyView();085.?85????????Log.i(TAG,‘--MyFragment->>onDestroyView‘);086.?86????}087.?87088.?88????//销毁fragment对象089.?89????@Override090.?90????publicvoidonDestroy() {091.?91????????// TODO Auto-generated method stub092.?92????????super.onDestroy();093.?93????????Log.i(TAG,‘--MyFragment->>onDestroy‘);094.?94????}095.?95096.?96????//脱离activity097.?97????@Override098.?98????publicvoidonDetach() {099.?99????????// TODO Auto-generated method stub100.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.????<LinearLayout09.????????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.1packagecom.example.m01_fragmentlifecycle;02.?203.?3importandroid.os.Bundle;04.?4importandroid.app.Activity;05.?5importandroid.app.FragmentManager;06.?6importandroid.app.FragmentTransaction;07.?7importandroid.util.Log;08.?8importandroid.view.Menu;09.?910.10publicclassMainActivityextendsActivity {11.11????privatefinalString TAG =‘MainActivity‘;12.12????privateFragmentManager manager;13.13????privateFragmentTransaction transaction;14.1415.15????@Override16.16????protectedvoidonCreate(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 =newMyFragment();22.22????????transaction.add(R.id.line, fragment);23.23????????transaction.commit();24.24????????Log.i(TAG,‘--MainActivity->>onCreate‘);25.25????}26.2627.27????@Override28.28????protectedvoidonStart() {29.29????????// TODO Auto-generated method stub30.30????????super.onStart();31.31????????Log.i(TAG,‘--MainActivity->>onStart‘);32.32????}33.3334.34????@Override35.35????protectedvoidonResume() {36.36????????// TODO Auto-generated method stub37.37????????super.onResume();38.38????????Log.i(TAG,‘--MainActivity->>onResume‘);39.39????}40.4041.41????@Override42.42????protectedvoidonPause() {43.43????????// TODO Auto-generated method stub44.44????????super.onPause();45.45????????Log.i(TAG,‘--MainActivity->>onPause‘);46.46????}47.4748.48????@Override49.49????protectedvoidonStop() {50.50????????// TODO Auto-generated method stub51.51????????super.onStop();52.52????????Log.i(TAG,‘--MainActivity->>onStop‘);53.53????}54.54????55.55????@Override56.56????protectedvoidonRestart() {57.57????????// TODO Auto-generated method stub58.58????????super.onRestart();59.59????????Log.i(TAG,‘--MainActivity->>onRestart‘);60.60????}61.61????@Override62.62????protectedvoidonDestroy() {63.63????????// TODO Auto-generated method stub64.64????????super.onDestroy();65.65????????Log.i(TAG,‘--MainActivity->>onDestroy‘);66.66????}67.6768.68????@Override69.69????publicbooleanonCreateOptionsMenu(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????????returntrue;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 =newRightFragment();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.1packagecom.example.m01_fragment04;02.?203.?3importandroid.app.Fragment;04.?4importandroid.os.Bundle;05.?5importandroid.view.LayoutInflater;06.?6importandroid.view.View;07.?7importandroid.view.ViewGroup;08.?809.?9publicclassFragment01extendsFragment {10.10????11.11????@Override12.12????publicvoidonCreate(Bundle savedInstanceState) {13.13????????super.onCreate(savedInstanceState);14.14????}15.15????16.16????@Override17.17????publicView onCreateView(LayoutInflater inflater, ViewGroup container,18.18????????????Bundle savedInstanceState) {19.19????????View view = inflater.inflate(R.layout.f1,null);20.20????????returnview;21.21????}22.22????@Override23.23????publicvoidonPause() {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.????<TextView08.????????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.????<LinearLayout08.????????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.????????<Button15.????????????android:id=‘@+id/button1‘16.????????????android:layout_width=‘wrap_content‘17.????????????android:layout_height=‘wrap_content‘18.????????????android:text=‘加载图片‘/>19.?20.????????<Button21.????????????android:id=‘@+id/button2‘22.????????????android:layout_width=‘wrap_content‘23.????????????android:layout_height=‘wrap_content‘24.????????????android:text=‘海报管理‘/>25.?26.????????<Button27.????????????android:id=‘@+id/button3‘28.????????????android:layout_width=‘wrap_content‘29.????????????android:layout_height=‘wrap_content‘30.????????????android:text=‘照片管理‘/>31.????32.????????<Button33.????????????android:id=‘@+id/button4‘34.????????????android:layout_width=‘wrap_content‘35.????????????android:layout_height=‘wrap_content‘36.????????????android:text=‘新闻管理‘/>???????37.?????????38.????</LinearLayout>39.?40.????<LinearLayout41.????????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.1packagecom.example.m01_fragment04;02.?203.?3importandroid.os.Bundle;04.?4importandroid.app.Activity;05.?5importandroid.app.FragmentManager;06.?6importandroid.app.FragmentTransaction;07.?7importandroid.view.Menu;08.?8importandroid.view.View;09.?9importandroid.view.View.OnClickListener;10.10importandroid.widget.Button;11.1112.12publicclassMainActivityextendsActivity?implementsOnClickListener{13.1314.14????privateFragmentManager manager;15.15????privateFragmentTransaction transaction;16.16????privateButton button1,button2,button3,button4;17.17????18.18????@Override19.19????protectedvoidonCreate(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.3435.35????@Override36.36????publicbooleanonCreateOptionsMenu(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????????returntrue;40.40????}41.4142.42????//通过点击不同的按钮,跳转到不同的Fragment43.43????@Override44.44????publicvoidonClick(View v) {45.45????????// TODO Auto-generated method stub46.<strong>46????????transaction = manager.beginTransaction();47.</strong>47????????switch(v.getId()) {48.48????????caseR.id.button1:49.49????????????Fragment01 fragment01 =newFragment01();50.50????????????transaction.replace(R.id.right, fragment01,‘fragment01‘);51.51????????????transaction.addToBackStack(‘fragment01‘);// 添加到Activity管理的回退栈中。52.52????????????break;53.5354.54????????caseR.id.button2:55.55????????????Fragment02 fragment02 =newFragment02();56.56????????????transaction.replace(R.id.right, fragment02,‘fragment02‘);57.57????????????transaction.addToBackStack(‘fragment02‘);// 添加到Activity管理的回退栈中。58.58????????????break;59.5960.60????????caseR.id.button3:61.61????????????Fragment03 fragment03 =newFragment03();62.62????????????transaction.replace(R.id.right, fragment03,‘fragment03‘);63.63????????????transaction.addToBackStack(‘fragment03‘);// 添加到Activity管理的回退栈中。64.64????????????break;65.6566.66????????caseR.id.button4:67.67????????????Fragment04 fragment04 =newFragment04();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