Google Doc: https://developer.android.google.cn/guide/components/fragments
一屈糊、Fragment生命周期
Activity對(duì)Fragment生命周期的影響
- onAttach()
在 Fragment 已與 Activity 關(guān)聯(lián)時(shí)調(diào)用(Activity 傳遞到此方法內(nèi))。 - onCreateView()
調(diào)用它可創(chuàng)建與 Fragment 關(guān)聯(lián)的視圖層次結(jié)構(gòu)。 - onActivityCreated()
在 Activity 的 onCreate() 方法已返回時(shí)調(diào)用返帕。 - onDestroyView()
在移除與 Fragment 關(guān)聯(lián)的視圖層次結(jié)構(gòu)時(shí)調(diào)用钻洒。 - onDetach()
在取消 Fragment 與 Activity 的關(guān)聯(lián)時(shí)調(diào)用。 - 一旦 Activity 達(dá)到 Resume 狀態(tài)石挂,就可以隨意向 Activity 添加/移除其中的 Fragment 崔泵。 因此秒赤,只有當(dāng) Activity 處于恢復(fù)狀態(tài)時(shí), Fragment 的生命周期才能獨(dú)立變化憎瘸。
- 當(dāng) Activity 離開 Resume 狀態(tài)時(shí)入篮, Fragment 會(huì)在 Activity 的推動(dòng)下再次經(jīng)歷其生命周期。
與 Activity 一樣幌甘,假使 Activity 的進(jìn)程被終止潮售,而又需要在重建 Activity 時(shí)恢復(fù) Fragment 狀態(tài),可以使用 Bundle 保留 Fragment 的狀態(tài)锅风∷址蹋可以在 Fragment 的 onSaveInstanceState() 回調(diào)期間保存狀態(tài),并可在 onCreate()皱埠、onCreateView() 或 onActivityCreated() 期間恢復(fù)狀態(tài)肮帐。
Activity 生命周期與 Fragment 生命周期之間的最顯著差異在于它們?cè)谄涓髯苑祷貤V械拇鎯?chǔ)方式。默認(rèn)情況下边器,Activity 停止時(shí)會(huì)被放入由系統(tǒng)管理的 Activity 返回棧(以便用戶通過“返回”按鈕回退到 Activity训枢,不過托修,僅當(dāng)在移除 Fragment 的事務(wù)執(zhí)行期間通過調(diào)用 addToBackStack()
顯式請(qǐng)求保存實(shí)例時(shí),系統(tǒng)才會(huì)將 Fragment 放入由宿主 Activity 管理的返回棧肮砾。
二诀黍、基本概念
Fragment核心類
- Fragment:Fragment的基類袋坑,任何創(chuàng)建的Fragment都需要繼承該類仗处。
- FragmentManager:管理和維護(hù)Fragment的抽象類,具體的實(shí)現(xiàn)類是- FragmentManagerImpl枣宫。
- FragmentTransaction:對(duì)Fragment的添加婆誓、刪除等操作都需要通過事務(wù)方式進(jìn)行。是抽象類也颤,具體的實(shí)現(xiàn)類是BackStackRecord洋幻。
- Nested Fragment:Fragment內(nèi)部嵌套Fragment的能力,Android 4.2提出的翅娶,support-fragment庫可以兼容到1.6文留。
- 通過getChildFragmentManager()能夠獲得管理子Fragment的FragmentManager,在子Fragment中可以通過getParentFragment()獲得父Fragment竭沫。
衍生類
DialogFragment
顯示浮動(dòng)對(duì)話框燥翅。使用此類創(chuàng)建對(duì)話框可有效地替代使用 Activity 類中的對(duì)話框幫助程序方法,可以將 Fragment 對(duì)話框納入由 Activity 管理的 Fragment 返回棧蜕提,從而使用戶能夠返回清除的 Fragment森书。
即使旋轉(zhuǎn)屏幕,也能保留對(duì)話框狀態(tài)谎势。
如果要自定義對(duì)話框樣式凛膏,只需要繼承DialogFragment,并重寫onCreateView()脏榆,該方法返回對(duì)話框UI猖毫。ListFragment
顯示由適配器(如 SimpleCursorAdapter)管理的一系列項(xiàng)目,類似于 ListActivity须喂。它提供了幾種管理列表視圖的方法鄙麦,如用于處理點(diǎn)擊事件的 onListItemClick() 回調(diào)。PreferenceFragment
以列表形式顯示 Preference 對(duì)象的層次結(jié)構(gòu)镊折,類似于 PreferenceActivity胯府。可以用來創(chuàng)建“設(shè)置” 頁面恨胚。
三骂因、Fragment通信
1 Fragment向Activity傳遞數(shù)據(jù)
實(shí)現(xiàn)步驟:
- 在Fragment中定義接口,并在Activity中實(shí)現(xiàn)該接口赃泡;
- 將實(shí)現(xiàn)注入Fragment寒波;
- Fragment中調(diào)用接口方法乘盼。
2 Activity向Fragment傳遞數(shù)據(jù)
實(shí)現(xiàn)步驟:
獲取Fragment對(duì)象,并調(diào)用Fragment的方法即可俄烁,如setXXX(XXX xxx)方法绸栅。
3 Fragment之間通信
Fragment之間是沒有任何依賴關(guān)系的,如果要進(jìn)行Fragment之間的通信页屠,需通過Activity作為中介粹胯,不要Fragment之間直接通信。
可使用EventBus
四辰企、Fragment懶加載
懶加載:當(dāng)Fragment完全可見的時(shí)候才去加載數(shù)據(jù)风纠。
主要用在ViewPager+Fragment場景下。
原因:
Fragment放在ViewPager里面時(shí)牢贸,ViewPager會(huì)預(yù)先加載左右相鄰的頁面竹观,但是很多時(shí)候我們也許只會(huì)去看第一個(gè),不會(huì)去看第二個(gè)潜索,如果這時(shí)候不實(shí)現(xiàn)Fragment的懶加載臭增,就會(huì)多余加載一些數(shù)據(jù),造成用戶多消耗流量竹习,所以建議采取懶加載的方式誊抛。
實(shí)現(xiàn)方式:
主要依賴Fragment的setUserVisibleHint(boolean isVisible)
方法,此方法會(huì)在 onCreateView()之前執(zhí)行由驹。
當(dāng)Fragment變?yōu)榭梢姇r(shí)芍锚,會(huì)調(diào)用setUserVisibleHint(true);當(dāng)Fragment變?yōu)椴豢梢姇r(shí)蔓榄,會(huì)調(diào)用setUserVisibleHint(false)并炮。
使用getUserVisibleHint()
可以獲取Fragment是否可見狀態(tài)。
示例:
以下示例引用自 https://blog.csdn.net/vic6329063/article/details/82838430
- 添加 isPrepared 參數(shù)甥郑。在系統(tǒng)調(diào)用onActivityCreated時(shí)設(shè)置為true逃魄,這時(shí)onCreateView方法已調(diào)用完畢(一般我們?cè)谶@方法里執(zhí)行findViewById等方法),確保 onLazyLoad()方法不會(huì)報(bào)空指針異常澜搅。
- 添加 isLazyLoaded 參數(shù)伍俘。確保ViewPager來回切換時(shí)BaseFragment的initData方法不會(huì)被重復(fù)調(diào)用,onLazyLoad在該Fragment的整個(gè)生命周期只調(diào)用一次勉躺,第一次調(diào)用onLazyLoad()方法后馬上執(zhí)行 isLazyLoaded = true癌瘾。
- getUserVisibleHint()會(huì)返回是否可見狀態(tài),這是Fragment實(shí)現(xiàn)懶加載的關(guān)鍵饵溅,只有Fragment 可見才會(huì)調(diào)用onLazyLoad() 加載數(shù)據(jù)妨退。
五、對(duì)Fragment的信息采集
SDK提供不同接口,分別對(duì)應(yīng)Fragment的各個(gè)生命周期咬荷,進(jìn)而采集信息冠句。使用時(shí),需要用戶在Fragment的生命周期的各個(gè)環(huán)節(jié)中幸乒,調(diào)用對(duì)應(yīng)的接口懦底。
使用比較麻煩。
解決方法:
封裝一個(gè)Fragment的子類罕扎,在子類中按照上述方法采集信息聚唐,開發(fā)時(shí)各Fragment直接繼承這個(gè)子類。