Fragment詳解

一. Fragment簡介

  • 我們都知道,Android上的界面展示都是通過Activity實(shí)現(xiàn)的塞栅,Activity實(shí)在是太常用了她君,我相信大家都已經(jīng)非常熟悉了,這里就不再贅述警没。但是Activity也有它的局限性匈辱,同樣的界面在手機(jī)上顯示可能很好看,在平板上就未必了杀迹,因?yàn)槠桨宓钠聊环浅4笸隽常謾C(jī)的界面放在平板上可能會有過分被拉長、控件間距過大等情況树酪。這個(gè)時(shí)候更好的體驗(yàn)效果是在Activity中嵌入"小Activity"浅碾,然后每個(gè)"小Activity"又可以擁有自己的布局。因此嗅回,我們今天的主角Fragment登場了及穗。

  • Android在3.0版本引入了Fragment功能摧茴, Fragment根據(jù)詞海的翻譯可以譯為:碎片绵载、片段。Fragment不可以單獨(dú)存在,是一種可以嵌入在活動當(dāng)中的UI片段娃豹,它能讓程序更加合理和充分地利用大屏幕焚虱,相比Activity更輕量級、更靈活懂版。它非常類似于Activity鹃栽,可以像Activity一樣包含布局。Fragment通常是嵌套在Activity中使用的躯畴。
    Fragment是在3.0版本引入的民鼓,如果你使用的是3.0之前的系統(tǒng),需要先導(dǎo)入android-support-v4的jar包才能使用Fragment功能蓬抄。


二. Fragment的生命周期

  • 每一個(gè)fragments 都有自己的一套生命周期回調(diào)方法和處理自己的用戶輸入事件丰嘉。 對應(yīng)生命周期可參考下圖:

1350998205_2002.png

因?yàn)镕ragment必須嵌入在Acitivity中使用,所以Fragment的生命周期和它所在的Activity是密切相關(guān)的嚷缭。如果Activity是暫停狀態(tài)饮亏,其中所有的Fragment都是暫停狀態(tài);如果Activity是stopped狀態(tài)阅爽,這個(gè)Activity中所有的Fragment都不能被啟動路幸;如果Activity被銷毀,那么它其中的所有Fragment都會被銷毀付翁。但是简肴,當(dāng)Activity在活動狀態(tài),可以獨(dú)立控制Fragment的狀態(tài)胆敞,比如加上或者移除Fragment着帽。

1. Fragment的幾種狀態(tài)

Fragment和activity一樣,也是有四種狀態(tài)

  • 活動狀態(tài):Resumed
    當(dāng)前Fragment位于前臺移层,用戶可見仍翰,可以獲得焦點(diǎn);
  • 暫停狀態(tài): Paused
    另一個(gè)Activity處于前臺并擁有焦點(diǎn), 但是該Fragment所在的Activity仍然可見(前臺Activity局部透明或者沒有覆蓋整個(gè)屏幕)观话,不過不能獲得焦點(diǎn)予借;
  • 停止?fàn)顟B(tài):Stopped
    要么是宿主Activity已經(jīng)被停止, 要么是Fragment從Activity被移除但被添加到回退棧中;停止?fàn)顟B(tài)的Fragment仍然活著(所有狀態(tài)和成員信息被系統(tǒng)保持著)频蛔。 然而, 它對用戶不再可見, 并且如果Activity被銷毀灵迫,它也會被銷毀;
  • 銷毀狀態(tài):Destroyed 只能等待被回收晦溪。

2.Fragment和Activity的對比

(1)活動和碎片之間的對比圖
2536652-a8cda6b9d53af55b.png
(2)由上圖可以看出瀑粥,F(xiàn)ragment比Activity多了幾個(gè)額外的生命周期回調(diào)方法:
  • onAttach() 當(dāng)碎片和活動建立關(guān)聯(lián)時(shí)調(diào)用。(獲得activity的傳遞的值)
  • onCreateView() 為碎片創(chuàng)建視圖調(diào)用就是加載布局時(shí)三圆。
  • onActivityCreated() 確保與碎片相關(guān)聯(lián)的活動一定已經(jīng)創(chuàng)建完畢的時(shí)候調(diào)用狞换。
  • onDestroyView() 當(dāng)與碎片的視圖被移除的時(shí)候調(diào)用避咆。
  • onDetach()當(dāng)碎片與活動解除關(guān)聯(lián)的時(shí)候調(diào)用。

三.如何使用Fragment

  • 靜態(tài)使用
  1. 繼承Fragment修噪,重寫onCreateView決定Fragemnt的布局
  2. 在Activity中聲明此Fragment查库,就當(dāng)和普通的View一樣
    關(guān)鍵代碼:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(layout, container, false); }

  • 動態(tài)添加
    1.創(chuàng)建待添加的碎片實(shí)例
    2.獲取到FragmentManager,在活動中可以直接調(diào)用getFragmentManager()方法得到黄琼。
    3.開啟一個(gè)事務(wù)樊销,通過調(diào)用beginTransaction()方法開啟
    4.向容器內(nèi)添加碎片,一般使用replace()方法脏款,需要傳入容器的id和待添加的碎片實(shí)例围苫。
    5.提交事務(wù),調(diào)用commit()(方法來完成撤师。
    關(guān)鍵代碼:

FragmentManager fm = getFragmentManager();
// 開啟Fragment事務(wù)
FragmentTransaction transaction = fm.beginTransaction();
//Fragment的布局替代控件
transaction.replace(控件的id, 碎片實(shí)例);
// 事務(wù)提交
transaction.commit();

  • 在碎片中模擬返回棧
    通過點(diǎn)擊按鈕添加了一個(gè)碎片之后够吩,這時(shí)按下back鍵程序就會直接退出。如果這里我們想模仿類似返回棧的效果丈氓,按下back鍵可以返回到上一個(gè)碎片周循,在FragmentTransaction中提供了一個(gè)addToBackStack()方法,可以用于將一個(gè)事務(wù)添加到返回棧中
    關(guān)鍵代碼:

transaction.addToBackStack(null);

注意: 在事務(wù)沒有提交之前添加代碼


四.Fragment的通信

Fragment和Activity之間的調(diào)用

  • 活動中調(diào)用碎片的方法:

為了方便碎片與活動之間進(jìn)行通信万俗,F(xiàn)ragmentManager提供了一個(gè)類似于findViewById()的方法湾笛,專門從布局文件中獲取碎片的實(shí)例,代碼如下:

Fragment fragment=(Fragment)getFragmentManager()
.findFragmentById(R.id.fragment);

調(diào)用 FragmentManager 的 findFragmentById()方法闰歪,可以在活動中得到相應(yīng)碎片的實(shí)例嚎研,這樣就可以調(diào)用碎片的方法了。

  • 碎片中調(diào)用活動的方法:

在每個(gè)碎片中都可以通過調(diào)用 getActivity()方法來得到和當(dāng)前碎片相關(guān)聯(lián) 的活動實(shí)例库倘,代碼如下:

MainActivity activity=(MainActivity)getActivity();

獲得活動實(shí)例后临扮,就可以在碎片中調(diào)用活動的方法。另外當(dāng)碎片中需要 使用 Context 對象時(shí)教翩,也可以使用 getActivity()方法杆勇,因?yàn)楂@取到的活動本身就是一個(gè)Context對象了。

Fragment和Activity之間的通信

  • ** Handler方案**
public class MainActivity extends FragmentActivity{ //聲明一個(gè)Handler  public Handler mHandler = new Handler(){ 
@Override 
public void handleMessage(Message msg) { 
super.handleMessage(msg);
 ...相應(yīng)的處理代碼
 }
 }
 ...相應(yīng)的處理代碼 
}
 public class MainFragment extends Fragment{
 //保存Activity傳遞的handler
 private Handler mHandler; 
@Override
 public void onAttach(Activity activity) { 
super.onAttach(activity);
 //這個(gè)地方已經(jīng)產(chǎn)生了耦合饱亿,若還有其他的activity蚜退,這個(gè)地方就得修改 
 if(activity instance MainActivity){ 
mHandler = ((MainActivity)activity).mHandler;
 }
 }
 ...相應(yīng)的處理代碼
 }

該方案存在的缺點(diǎn):
Fragment對具體的Activity存在耦合,不利于Fragment復(fù)用
不利于維護(hù)彪笼,若想刪除相應(yīng)的Activity钻注,F(xiàn)ragment也得改動
沒法獲取Activity的返回?cái)?shù)據(jù)

  • EventBus方案
    主要功能是替代Intent,Handler,BroadCast在Fragment,Activity配猫,Service幅恋,線程之間傳遞消息.優(yōu)點(diǎn)是開銷小,代碼更優(yōu)雅泵肄。以及將發(fā)送者和接收者解耦捆交。
    1识埋、下載EventBus的類庫源碼:https://github.com/greenrobot/EventBus
    2、基本使用
    (1)自定義一個(gè)類零渐,可以是空類,比如:
public class AnyEventType {  
     public AnyEventType(){}  
 }  

(2)在要接收消息的頁面注冊:

eventBus.register(this);  

(3)發(fā)送消息

eventBus.post(new AnyEventType event);  

(4)接受消息的頁面實(shí)現(xiàn)(共有四個(gè)函數(shù)系忙,各功能不同诵盼,這是其中之一,可以選擇性的實(shí)現(xiàn)银还,這里先實(shí)現(xiàn)一個(gè)):

public void onEvent(AnyEventType event) {}  

(5)解除注冊

eventBus.unregister(this); 

注意:在EventBus中风宁,獲取實(shí)例的方法一般是采用EventBus.getInstance()來獲取默認(rèn)的EventBus實(shí)例,當(dāng)然你也可以new一個(gè)實(shí)例蛹疯。

  • setArguments(Bundle bundle)方案:
 public class ExampleFragment extends Fragment{
 private String type; 
public static ExampleFragment newInstance(String type) { 
ExampleFragment myFragment = new ExampleFragment(); 
Bundle args = new Bundle(); 
args.putString("type", type);
//發(fā)送要傳遞的值
myFragment.setArguments(args);
return myFragment; 
} 
@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
//接收數(shù)據(jù)
type=getArguments().getString("type");
 ...相應(yīng)的處理代碼
 }
}

這種activity向fragment傳值方法是最簡單有效的戒财,而且在fragment異常重建的時(shí)候bundle將參數(shù)保存了下來

  • ** 使用接口回調(diào)的方法通信(推薦)**
//MainActivity 實(shí)現(xiàn)MainFragment的接口
public class MainActivity extends FragmentActivity implements FragmentListener{ 
@override
 public void toInterface (){ } ...其他處理代碼省略 }
public class MainFragment extends Fragment{ 
public FragmentListener mListener;
 //MainFragment開放的接口 
public static interface FragmentListener{ 
void toInterface (); }
 @Override 
public void onAttach(Activity activity) {
 super.onAttach(activity); 
//對傳遞進(jìn)來的Activity進(jìn)行接口轉(zhuǎn)換 
if(activity instance FragmentListener){ 
mListener = ((FragmentListener)activity);
 } } ...其他處理代碼省略 }

這種方案應(yīng)該是既能達(dá)到復(fù)用,又能達(dá)到很好的可維護(hù)性捺弦,并且性能很好(推薦使用)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末饮寞,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子列吼,更是在濱河造成了極大的恐慌幽崩,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寞钥,死亡現(xiàn)場離奇詭異慌申,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)理郑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門蹄溉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人您炉,你說我怎么就攤上這事柒爵。” “怎么了赚爵?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵餐弱,是天一觀的道長。 經(jīng)常有香客問我囱晴,道長膏蚓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任畸写,我火速辦了婚禮驮瞧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘枯芬。我一直安慰自己论笔,他們只是感情好采郎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著狂魔,像睡著了一般蒜埋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上最楷,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天整份,我揣著相機(jī)與錄音,去河邊找鬼籽孙。 笑死烈评,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的犯建。 我是一名探鬼主播讲冠,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼适瓦!你這毒婦竟也來了竿开?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤玻熙,失蹤者是張志新(化名)和其女友劉穎德迹,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體揭芍,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胳搞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了称杨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肌毅。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖姑原,靈堂內(nèi)的尸體忽然破棺而出悬而,到底是詐尸還是另有隱情,我是刑警寧澤锭汛,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布笨奠,位于F島的核電站,受9級特大地震影響唤殴,放射性物質(zhì)發(fā)生泄漏般婆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一朵逝、第九天 我趴在偏房一處隱蔽的房頂上張望蔚袍。 院中可真熱鬧,春花似錦配名、人聲如沸啤咽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宇整。三九已至瓶佳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鳞青,已是汗流浹背霸饲。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留盼玄,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓潜腻,卻偏偏與公主長得像埃儿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子融涣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,077評論 25 707
  • 一童番、使用詳解 (1)Handler使用 (2)Handler構(gòu)造方法 Handler():構(gòu)造函數(shù)將通過調(diào)用Loo...
    kjy_112233閱讀 669評論 0 0
  • 1、概述首先我們簡單回顧一下威鹿,相信大家對Fragment的都不陌生剃斧,對于Fragment的使用,一方面Activi...
    大鴨梨leepear閱讀 362評論 0 1
  • "在城里打工賺錢半年終于可以回家了忽你,花花上次打電話說考了第一呢幼东,可得買一盒草莓獎(jiǎng)勵(lì)她!"何小草想科雳。何小草根蟹,單身離異...
    棠梨汁閱讀 420評論 2 3
  • 圖片發(fā)自簡書App一生至少該有一次 ,為了某個(gè)人而忘了自己 糟秘,不求有結(jié)果 简逮,不求同行 ,不求曾經(jīng)擁有 尿赚,甚至不求你...
    Fancy_2016閱讀 584評論 2 10