黃立明+江有福+陸雅男
摘要:以傳統(tǒng)的方式實(shí)現(xiàn)多級(jí)選項(xiàng)列表,不僅構(gòu)建困難,而且不利于管理,缺乏靈活性,這種情況在Android 3.0引入了Fragment技術(shù)之后得到改善。Fragment技術(shù)支持更加靈活的UI設(shè)計(jì),增強(qiáng)了對(duì)平板和手機(jī)的兼容性,為多級(jí)選項(xiàng)列表的實(shí)現(xiàn)提供了一種全新的設(shè)計(jì)思路。本文完整地介紹Fragment的生命周期,并通過(guò)詳細(xì)的實(shí)例制作過(guò)程體現(xiàn)其靈活和便于管理的特性。
關(guān)鍵詞:安卓;碎片;用戶(hù)界面;多級(jí)選項(xiàng)列表
中圖分類(lèi)號(hào):G642 文獻(xiàn)標(biāo)志碼:A 文章編號(hào):1674-9324(2015)15-0153-04
0 引言
Fragment中文意思是碎片,用于在一個(gè)Activity中描述部分操作界面和相關(guān)的行為。使用Fragment分散整個(gè)Activity的布局,體現(xiàn)出了良好的模塊化思維,提高了碎片的重用性。Fragment技術(shù)出現(xiàn)之前,多級(jí)選項(xiàng)列表的實(shí)現(xiàn)方式是先設(shè)置布局,再控制各級(jí)列表對(duì)應(yīng)視圖的展現(xiàn)或隱藏。這樣做,更多關(guān)注的是視圖層次的變化,但是根據(jù)線(xiàn)程安全的原則,在子線(xiàn)程中不能直接修改UI界面,難以實(shí)現(xiàn)靈活管理。雖然可以使用Handler消息機(jī)制解決靈活管理的問(wèn)題,但是Handler機(jī)制比較煩瑣,容易導(dǎo)致代碼臃腫。然而使用Fragment,則不需要親自管理視圖層次的復(fù)雜變化,會(huì)在程序運(yùn)行時(shí)修改Activity的外觀。所以我們依據(jù)Fragment靈活的特性來(lái)實(shí)現(xiàn)多級(jí)選項(xiàng)列表,同時(shí)保持了良好的代碼風(fēng)格。
圖1是Fragment和Activity生命周期的對(duì)比圖。Fragment作為Activity的一部分,擁有一個(gè)與其相關(guān)的視圖層次結(jié)構(gòu)以及與Activity非常相似的生命周期。
1 Fragment初始化
Fragment并非Activity的子類(lèi),F(xiàn)ragment直接繼承Object,而Activity直接繼承ContextThemeWrapper。
2 Fragment的生命周期
2.1 onAttach()
當(dāng)Fragment附加到Activity時(shí),該回調(diào)方法會(huì)被調(diào)用。此方法中可以通過(guò)getActivity()方法獲得附加的Activity,將Fragment附加到Activity前,可以使用setArguments()方法附加參數(shù)到一個(gè)Bundle對(duì)象(初始化參數(shù)包)。在Fragment的整個(gè)生命周期中,初始化參數(shù)包都可以用Fragment的getArguments()方法獲得。
2.2 onCreate()
此回調(diào)發(fā)生在Activity需要獲取Fragment的布局時(shí)。如果Fragment是恢復(fù)的,則該回調(diào)過(guò)程中可以獲取傳入的Bundle型對(duì)象包savedInstanceState,這個(gè)對(duì)象包保存了Fragment的上一狀態(tài)數(shù)據(jù),也可以在onCreateView()和onActivityCreated()中獲取該對(duì)象包。這個(gè)過(guò)程中應(yīng)當(dāng)盡量避免可能阻塞主線(xiàn)程的操作,例如獲取網(wǎng)絡(luò)數(shù)據(jù),登陸驗(yàn)證等。
2.3 onCreateView()
此回調(diào)發(fā)生在Fragment繪制界面并返回一個(gè)根視圖時(shí),如果不需要視圖層次,可以返回null。該方法的聲明中包含三個(gè)參數(shù),分別是inflater,container,savedInstanceState。inflater參數(shù)可以調(diào)用inflate()方法動(dòng)態(tài)加載一個(gè)xml布局文件來(lái)返回視圖;container參數(shù)指定需要插入fragment布局的父容器;savedInstanceState參數(shù)不再贅述。
2.4 onActivityCreated()
此回調(diào)過(guò)程發(fā)生在Activity的onCreate()回調(diào)之后,可以存在需要依賴(lài)于Activity視圖層次的代碼,例如進(jìn)行一些屬性的設(shè)置。
2.5 其他
只有當(dāng)Activity處于resumed狀態(tài)時(shí),F(xiàn)ragment的生命周期才得以獨(dú)立運(yùn)轉(zhuǎn),其他它時(shí)候是依賴(lài)于Activity的生命周期變化的。這種綁定Activity的時(shí)期包含了onStart()回調(diào)、onResume()回調(diào)、onPause()回調(diào)以及onStop()回調(diào)。因?yàn)槲覀儾淮_定用戶(hù)是否還會(huì)返回,在onPause()方法中通常做一些數(shù)據(jù)持久化的工作,再通過(guò)onSaveInstanceState()方法保存Fragment的狀態(tài)值。
3 創(chuàng)建Fragment
創(chuàng)建Fragment首先需要?jiǎng)?chuàng)建擴(kuò)展Fragment類(lèi)的Java類(lèi),并重寫(xiě)其onCreateView()方法,在這個(gè)方法中按具體的方式創(chuàng)建碎片。
3.1 加載布局式
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState){
View v = inflater.inflate(R.layout.content,null);
}
該方式通過(guò)LayoutInflater類(lèi)的對(duì)象inflater調(diào)用inflate()方法加載xml布局文件來(lái)創(chuàng)建Fragment。示例代碼中加載的是content.xml布局文件。
3.2 Java代碼式
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState){
//構(gòu)建Fragment的java代碼
}
該方式通過(guò)在onCreateView()方法中書(shū)寫(xiě)java代碼來(lái)構(gòu)建Fragment。
4 顯示Fragment
在Activity中顯示Fragment主要有兩種方式,分別是靜態(tài)載入xml布局方式和動(dòng)態(tài)管理方式。第一種方式是對(duì)碎片進(jìn)行布局,盡管這種方式已經(jīng)夠用,但是為了更好的實(shí)現(xiàn)運(yùn)行時(shí)刻與屏幕上的碎片交互,還需引入動(dòng)態(tài)管理的方式。
4.1 靜態(tài)載入xml
該方式是通過(guò)在Activity的xml布局文件中定義一個(gè)或多個(gè)
4.2 動(dòng)態(tài)管理
該方式需要借助Android系統(tǒng)控制碎片的工具FragmentManager來(lái)實(shí)現(xiàn)的。需要注意的是,xml布局中使用
實(shí)現(xiàn)步驟如下:
(1)先調(diào)用指定類(lèi)的初始化函數(shù)實(shí)例化Fragment。
(2)再使用getFragmentManager()方法獲取FragmentManager,并通過(guò)其提供的接口方法beginTransaction()返回一個(gè)FragmentTransaction的實(shí)例。
(3)然后設(shè)置Fragment的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)。
(4)再指定方式(replace、remove、add)和需要替換為碎片的視圖容器(第一個(gè)參數(shù))。
(5)最后提交事務(wù)。
對(duì)應(yīng)代碼如下圖所示。
5 制作多級(jí)選項(xiàng)列表
使用安卓開(kāi)發(fā)工具ADT設(shè)計(jì)應(yīng)用程序時(shí),首先需要編寫(xiě)應(yīng)用程序主界面Activity的xml布局文件,然后其余的工作交由java過(guò)程設(shè)計(jì)代碼來(lái)處理。通常編程人員在繼承使用系統(tǒng)類(lèi)的時(shí)候,會(huì)依照實(shí)際開(kāi)發(fā)需求擴(kuò)展需要的功能。此處我們需要擴(kuò)展使用ListFragment,實(shí)現(xiàn)其中的onListItemClick()方法來(lái)響應(yīng)用戶(hù)的點(diǎn)擊事件。
5.1 Activity的xml布局
5.2 一級(jí)列表
主要代碼如圖3所示。
代碼分析:
一級(jí)列表類(lèi)TitleFragment用于顯示一級(jí)列表,是以靜態(tài)形式首先被加載,所以不需要初始化,即不需要顯式的構(gòu)造函數(shù)。在Activity調(diào)用setContentView()方法設(shè)置視圖時(shí),F(xiàn)ragment通過(guò)xml文件中〈fragment〉標(biāo)記映射對(duì)應(yīng)的類(lèi)。
第3~10行:在onCreate()方法中準(zhǔn)備列表的數(shù)據(jù);
第11~13行:在onCreate()方法中指定適配器;
第17行:在OnActivityCreated()方法中為列表設(shè)置適配器;
第22行:重寫(xiě)ListFragment的onListItemClick()方法,其中調(diào)用showDetails()方法;
第27~31行:在showDetails()方法中使用動(dòng)態(tài)管理的方式顯示二級(jí)列表視圖。
實(shí)現(xiàn)效果如圖4所示。
5.3 二級(jí)列表
5.3.1 主要代碼如圖5所示。
代碼分析:
二級(jí)列表類(lèi)DetailFragment1用于顯示二級(jí)列表,因?yàn)槎?jí)列表需要根據(jù)一級(jí)列表的選中值來(lái)動(dòng)態(tài)選擇該列表所要顯示的內(nèi)容,所以需要顯式的寫(xiě)出初始化函數(shù)。
第1~2行:顯式的初始化函數(shù)newInstance()中實(shí)例化DetailFragment1_triage;
第3~6行:使用bundle包保存二級(jí)列表的狀態(tài),并返回DetailFragment1_triage類(lèi)的對(duì)象df;
第11~13行:在onCreateView()方法中,為listview設(shè)置適配器;
第14行:給listview設(shè)定選擇模式;
第16行:返回視圖listview;
第23行:重寫(xiě)onListItemClick()方法中調(diào)用showDetails()方法;
第26~27行:在showDetails()方法中使用動(dòng)態(tài)管理的方式顯示三級(jí)列表。
實(shí)現(xiàn)效果如圖6所示。
5.4 三級(jí)列表
三級(jí)列表類(lèi)DetailFragment2的實(shí)現(xiàn)和二級(jí)列表類(lèi)DetailFragment1的實(shí)現(xiàn)類(lèi)似。
6 最終效果
7 總結(jié)
本文基于對(duì)Fragment生命周期的理解,挖掘了Fragment技術(shù)的使用范圍,提供了一種新的基于Fragment技術(shù)實(shí)現(xiàn)多級(jí)選項(xiàng)列表的方法。
基于Fragment技術(shù)的應(yīng)用程序設(shè)計(jì)體現(xiàn)了如下的幾大特性。
(1)對(duì)Android手機(jī)和平板有良好的兼容性。
(2)Fragment對(duì)應(yīng)用程序框架構(gòu)建的支持,淘汰了陳舊的TabActivity和ActivityGroup。
(3)Fragment分散Activity的特性大大提升Fragment代碼的重用性。
參考文獻(xiàn):
[1]王云林.Android應(yīng)用中跨版本集成新特性的研究與實(shí)現(xiàn)[D].上海:東華大學(xué)計(jì)算機(jī)系,2013.
[2]史書(shū)明.Android應(yīng)用中消息傳遞方法分析[J].電腦知識(shí)與技術(shù),2014,10(13):2984-2986.
[3]李剛.瘋狂Android講義[M].北京:電子工業(yè)出版社,2013.
[4]王濤.安卓系統(tǒng)消息傳遞方法研究[J].安陽(yáng)工學(xué)院學(xué)報(bào),2014,13(4):61-63.
[5]Chris Haseman.Android應(yīng)用開(kāi)發(fā)[M].北京:人民郵電出版社,2013:172-178.