Fragment有兩種方式生成案淋,一是硬編碼到xml文件中仓洼,二是在Java代碼中new介陶,然后通過(guò)FragmentManager#beginTransaction開(kāi)啟FragmentTransaction提交來(lái)添加Fragment(下文會(huì)介紹)。兩種方式存在著一定區(qū)別.硬編碼到xml的Fragment無(wú)法被FragmentTransition#remove移除衬潦,與Activity同生共死斤蔓,所以你要是這么用了,就不用試了,移除不了的镀岛,但是在代碼中new出來(lái)的是可以被移除的弦牡。
直接硬編碼到xml中:
<fragment
android:id="@+id/map_view"
android:name="org.kexie.android.dng.navi.widget.AMapCompatFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
添加Fragment的第二種方式就是使用FragmentManager#beginTransaction(代碼如下)動(dòng)態(tài)添加,你需要先new一個(gè)Fragment漂羊,然后通過(guò)下面Fragment#requireFragmentManager獲取FragmentManager來(lái)使用beginTransaction添加Fragment驾锰,注意add方法的第一個(gè)參數(shù),你需要給它指定一個(gè)id走越,也就是Fragment容器的id椭豫,通常容器是一個(gè)沒(méi)有子View的FrameLayout,它決定了這個(gè)Fragment要在什么位置顯示旨指。
//在xml中編寫(xiě)放置Fragment位置的容器
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
在Fragment中赏酥,我們可以使用getId()可以返回自身的id,通常用這個(gè)方法返回它所在的容器的id谆构,供其他Fragment添加進(jìn)也添加到當(dāng)前容器時(shí)使用(例如使用Fragment返回棧的場(chǎng)景)裸扶。
/**
* Return the identifier this fragment is known by. This is either
* the android:id value supplied in a layout or the container view ID
* supplied when adding the fragment.
*/
final public int getId() {
return mFragmentId;
}
需要注意的是FragmentTransaction并不是立即執(zhí)行的,而是在當(dāng)前代碼執(zhí)行完畢后,回到事件循環(huán)(也就是你們知道的Looper)時(shí)搬素,才會(huì)執(zhí)行呵晨,不過(guò)他會(huì)保證在下一幀渲染之前得到執(zhí)行(通過(guò)Handler#createAsync機(jī)制),若要在FragmentTransaction執(zhí)行時(shí)搞事情熬尺,你需要使用runOnCommit摸屠,在上面的代碼中我使用了Java8的lambda表達(dá)式簡(jiǎn)寫(xiě)了Runnable。
如果你還想使用Fragment回退棧記得調(diào)用addToBackStack粱哼,最后別忘了commit,這樣才會(huì)生效季二,此時(shí)commit函數(shù)返回的是BackStackEntry的id.
Fragment生命周期
onInflate(Context,AttributeSet,Bundle)只有硬編碼在xml中的Fragment(即使用fragment標(biāo)簽)才會(huì)回調(diào)此方法,這與自定義View十分類(lèi)似揭措,在實(shí)例化xml布局時(shí)該方法會(huì)被調(diào)用,先于onAttach.
onAttach(Context)執(zhí)行該方法時(shí)戒傻,F(xiàn)ragment與Activity已經(jīng)完成綁定,當(dāng)一個(gè)Fragment被添加到FragmentManager時(shí),如果不是在xml中直接定義fragment標(biāo)簽,那么該方法總是最先被回調(diào).該方法傳入一個(gè)Context對(duì)象税手,實(shí)際上就是該Fragment依附的Activity.重寫(xiě)該方法時(shí)記得要調(diào)用父類(lèi)的super.onAttach,父類(lèi)的onAttach調(diào)用返回后,此時(shí)調(diào)用getActivity將不會(huì)返回null,但是Activity#onCreate可能還有沒(méi)有執(zhí)行完畢(如果是在xml中定義,這種情況就會(huì)發(fā)生,因?yàn)榇藭r(shí)這個(gè)回調(diào)的這個(gè)發(fā)生的時(shí)間也就是你在Activity#onCreate里setContentView的時(shí)間,直到Fragment#onViewCreated返回之后,Activity#onCreate才會(huì)繼續(xù)執(zhí)行)需纳。
onCreate(Bundle)用來(lái)初始化Fragment芦倒。它總是在onAttach執(zhí)行完畢后回調(diào),可通過(guò)參數(shù)savedInstanceState獲取之前保存的值,記得一定要調(diào)用父類(lèi)的super.onCreate。
onCreateView(LayoutInflater,ViewGroup,Bundle)需要返回一個(gè)View用來(lái)初始化Fragment的布局,它總是在onCreate執(zhí)行完畢后回調(diào)不翩。默認(rèn)返回null兵扬,值得注意的是,若返回null Fragment#onViewCreated將會(huì)被跳過(guò),且如果是在xml中定義fragment標(biāo)簽并用name指定某個(gè)Fragment,則這個(gè)方法不允許返回null,否則就會(huì)報(bào)錯(cuò)口蝠。當(dāng)使用ViewPager+Fragment時(shí)此方法可能會(huì)被多次調(diào)用(與Fragment#onDestroyView成對(duì)調(diào)用)器钟。
onActivityCreated(Bundle)執(zhí)行該方法時(shí),與Fragment綁定的Activity的onCreate方法已經(jīng)執(zhí)行完成并返回妙蔗,若在此方法之前與Activity交互交互沒(méi)有任何保證傲霸,引用了未初始化的資源就會(huì)應(yīng)發(fā)空指針異常。
onStart()執(zhí)行該方法時(shí)眉反,F(xiàn)ragment所在的Activity由不可見(jiàn)變?yōu)榭梢?jiàn)狀態(tài)
onResume()執(zhí)行該方法時(shí)昙啄,F(xiàn)ragment所在的Activity處于活動(dòng)狀態(tài),用戶(hù)可與之交互.
onPause()執(zhí)行該方法時(shí)寸五,F(xiàn)ragment所在的Activity處于暫停狀態(tài)梳凛,但依然可見(jiàn),用戶(hù)不能與之交互,比如Dialog蓋住了Activity
onStop()執(zhí)行該方法時(shí)梳杏,F(xiàn)ragment所在的Activity完全不可見(jiàn)
onSaveInstanceState(Bundle)保存當(dāng)前Fragment的狀態(tài)韧拒。該方法會(huì)自動(dòng)保存Fragment的狀態(tài),比如EditText鍵入的文本十性,即使Fragment被回收又重新創(chuàng)建叛溢,一樣能恢復(fù)EditText之前鍵入的文本,說(shuō)實(shí)話我不太喜歡這個(gè)方法,保存到Bundle里的設(shè)計(jì)實(shí)在是太蠢了,不過(guò)好在現(xiàn)在已經(jīng)有了代替它的方案,Google的Android Jetpack MVVM框架,之后我也會(huì)專(zhuān)門(mén)出一篇文章來(lái)介紹。
onDestroyView()銷(xiāo)毀與Fragment有關(guān)的視圖劲适,但未與Activity解除綁定雇初,一般在這個(gè)回調(diào)里解除Fragment對(duì)視圖的引用。通常在ViewPager+Fragment的方式下會(huì)使用并重寫(xiě)此方法减响,并且與Fragment#onCreateView一樣可能是多次的。
onDestroy()銷(xiāo)毀Fragment郭怪。通常按Back鍵退出或者Fragment被移除FragmentManager時(shí)調(diào)用此方法支示,此時(shí)應(yīng)該清理Fragment中所管理的所有數(shù)據(jù),它會(huì)在onDetach之前回調(diào)。
onDetach()解除與Activity的綁定鄙才。在onDestroy方法之后調(diào)用。Fragment生命周期的最末期,若在super.onDetach返回后getActivity(),你將會(huì)得到一個(gè)null缓苛。