
3.4 Fragment的使用
Fragment(片段)以Activity界面的一个组成部分出现。
3.4.1 Fragment的生命周期
Fragment有自己的生命周期,但它的生命周期受其所在的Activity生命周期控制,Fragment不能独立存在,它必须嵌入到Activity中。当Activity暂停时,它拥有的所有的Fragment都暂停了;当Activity销毁时,它拥有的所有Fragment都被销毁;当Activity处于活动状态时(在onResume()之后,onPause()之前),用户可以通过方法操作每个Fragment。Fragment的生命周期如图3.6所示。
Fragment有以下特点:
- Fragment总是作为Activity界面的组成部分。
- Fragment有自己的生命周期,但它的生命周期被其所属的Activity生命周期控制。
- 在Activity运行过程中,可动态地添加、删除和替换Fragment。

图3.6 Fragment生命周期
- 一个Activity中可同时出现多个Fragment,一个Fragment也可在多个Activity中使用。
- Fragment可以响应自己的输入事件。
1.Fragment对象跟用户交互时需要回调的方法
1)onAttach(Activity)
当Fragment对象跟Activity关联时,调用该方法。
2)onCreate(Bundle)
当Fragment对象初始创建时,调用该方法。
3)onCreateView(LayoutInflater,ViewGroup,Bundle)
该方法用于创建和返回跟Fragment关联的View对象。
4)onActivityCreate(Bundle)
该方法会告诉Fragment对象,它所依附的Activity对象已经完成了Activity.onCreate()方法的执行。
5)onStart()
该方法会让Fragment对象显示给用户(在包含该Fragment对象的Activity被启动后)。
6)onResume()
该方法会让Fragment对象跟用户交互(在包含该Fragment对象的Activity被启动恢复后)。
2.Fragment对象不再使用时需要回调的方法
1)onPause()
当Fragment对象所依附的Activity对象被挂起,或者在Activity中正在执行一个修改Fragment对象的操作,而导致Fragment对象不再跟用户交互时,系统会调用该方法。
2)onStop()
当Fragment对象所依附的Activity对象被终止,或者在Activity中正在执行一个修改Fragment对象的操作,而导致Fragment对象不再显示给用户时,系统会调用该方法。
3)onDestroyView()
该方法用于清除跟Fragment中的View对象关联的资源。
4)onDestroy()
当Fragment对象的状态被最终清理完成之后,要调用该方法。
5)onDetach()
当Fragment对象不再跟它依附的Activity关联的时候,该方法会立即被调用。
3.4.2 Fragment的应用
Fragment在应用中是一个模块化和可重用的组件,下面介绍向Activity中添加Fragment的方法、Fragment常用的类和方法、Fragment的子类等内容。
1.向Activity中添加Fragment的方法
向Activity中添加Fragment有两种方法:一种是直接在布局文件中添加,另一种是当Activity运行时添加。
1)直接在布局文件中添加Fragment
直接在布局文件中添加Fragment,可以使用<fragment>标记实现,将Fragment作为Activity整个布局的一部分。
2)当Activity运行时添加Fragment
当Activity运行时,也可以将Fragment添加到Activity的布局中,实现方法是获取一个FragmentTransaction的实例,然后使用add()方法添加一个Fragment,再调用commit()方法提交事务。
2.Fragment常用的类
(1)android.app.Fragment:用于定义Fragment。
(2)android.app.FragmentManager:用于在Activity中操作Fragment。通过调用Activity的getFragmentManager()方法可以取得FragmentManager的实例。
(3)android.app.FragmentTransaction:对Fragment进行添加、移除、替换及执行其他动作。
在使用FragmentTransaction的方法前,首先需要取得FragmentManager的实例,再利用FragmentManage的beginTransaction()方法开启一个事务,获取一个FragmentTransaction对象。
3.FragmentTransaction的方法
(1)FragmentTransaction.add():往Activity中添加一个Fragment。
(2)FragmentTransaction.remove():从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁。回退栈(back stack)由Activity管理,允许用户通过按下Back按键返回到前一个Fragment状态。
(3)FragmentTransaction.replace():使用另一个Fragment替换当前的Fragment。
(4)FragmentTransaction.hide():隐藏当前的Fragment,仅仅是设为不可见,并不会销毁。
(5)FragmentTransaction.show():显示之前隐藏的Fragment。
(6)FragmentTransaction.detach():会将View从UI中移除,和remove()不同,此时Fragment的状态依然由FragmentManager维护。
(7)FragmentTransaction.attach():重建View视图,附加到UI上并显示。
(8)FragmentTransaction.commit():提交一个事务。在一个事务开启到提交可以进行多个Fragment的添加、移除和替换等操作。需要注意,FragmentTransaction的commit()方法一定要在Activity.onSaveInstance()方法之前调用。
4.Fragment的子类
Fragment有以下子类,可实现不同类型的UI面板。
(1)DialogFragment类:显示一个浮动的对话框。
(2)ListFragment类:显示一个由Adapter管理项目的列表,类似于ListActivity,它提供一些方法来管理一个ListView,使用onListItemClick回调来处理单击事件。
(3)PreferenceFragment类:显示一个Preference对象的层次结构的列表,类似于PreferenceActivity。
Android引入Fragment的初衷是为了适应大屏幕的平板电脑,下面的例题介绍使用Fragment模拟平板电脑的显示。
【例3.2】 模拟平板电脑划分为左右两个片段,分别显示Java概念列表和定义。
【解题思路】
在Activity界面左部的Fragment显示Java概念列表项,当单击某一列表项时,右部Fragment进行动态更新,显示对应的Java概念定义。
【开发步骤和程序分析】
(1)在Eclipse中创建一个ActivityFragment应用项目,包名为com.application.activityfragment。
(2)设计布局。
布局文件为activitytwopanes.xml和fragmentdetail.xml。
在res/layout目录下的activitytwopanes.xml文件中,左部添加一个Fragment元素,右部添加一个FrameLayout容器。
该文件编辑代码如下。

在res/layout目录下的fragmentdetail.xml文件中包含两个文本框,上边的文本框用于显示概念名称,下边的文本框用于显示概念内容。
该文件编辑代码如下:

(3)在com.application.activityfragment包下的ActivityFragmentConcept.java文件中,加载activitytwopane.xml布局文件并实现Callbacks接口,该Activity左部的Fragment显示Java概念列表项,右部Fragment显示Java概念定义并进行动态更新。
该文件编辑代码如下:

① 第8行至第36行定义一个类ActivityFragmentConcept继承Activity类,且实现Callbacks接口。
② 第13行至第19行重写onCreate()方法,第18行加载/res/layout目录下的activitytwopanes.xml布局文件。
③ 第21行至第35行重写onItemSelected()方法,这是实现Callbacks接口必须实现的方法,第25行至第26行创建Bundle,准备向Fragment传入参数,第28行为创建FragmentDetailConcept对象fragment,第30行向Fragment传入参数,第32行至第34行使用fragment替换concept_detail_container容器当前显示的Fragment。
(4)下面的Fragment将会加载fragmentdetail.xml布局文件,构成Activity界面的右部,并根据传入的参数更新该部分。
在com.application.activityfragment包下的FragmentDetailConcept.java文件中,编辑代码如下:


① 第13行至第51行定义一个类FragmentDetailConcept继承Fragment类。
② 第20行至第30行重写onCreate()方法。
③ 第33行至第50行重写onCreateView()方法,该方法返回的View将作为Fragment显示的组件,第38行至第39行加载/res/layout/目录下的fragmentdetail.xml布局文件,构成Activity界面的右部,第43行至第44行让concept_title文本框显示concept对象的title属性,第46行至第47行让concept_desc文本框显示concept对象的desc属性。
(5)下面的Fragment开发了一个ListFragment的子类,调用setListAdapter()方法设置Adapter,构成Activity界面的左部的列表项。
在com.application.activityfragment包下的FragmentListConcept.java文件中,编辑代码如下:


① 第12行至第72行定义一个类FragmentListConcept继承ListFragment类。
② 第17行至第20行重写onCreate()方法,定义一个回调接口Callbacks,该Fragment所在Activity需要实现该接口,该Fragment将通过该接口与它所在的Activity交互。
③ 第23行至第31行重写onCreate()方法,第28行至第30行为该ListFragment设置Adapter。
④ 第34行至第46行重写onAttach()方法,重写onDetach()方法,当该Fragment从它所属的Activity中被删除时回调该方法。
⑤ 第56行至第64行重写onListItemClick()方法,当用户单击某列表项时激发该回调方法。
(6)下面的ConceptData类使用List集合和Map集合记录系统所包含的Concept对象。
在com.application.activityfragment.model包下的ConceptData.java文件中,编辑代码如下:


① 第9行至第59行定义一个类ConceptData。
② 第33行使用List集合记录系统所包含的Concept对象,第35行使用Map集合记录系统所包含的Concept对象。
③ 第41行至第51行使用静态初始化代码,将Concept对象添加到List集合、Map集合中。
【运行结果】
在Eclipse中启动模拟器,然后运行项目ActivityFragment,当左部Fragment的“继承(Inheritance)”列表项被选中,右部Fragment出现该条目的名称和内容,如图3.7所示。

图3.7 ActivityFragment运行结果