【正文】
一、fragment的生命周期初探:
因為fragment必須嵌入在acitivity中使用,是以fragment的生命周期和它所在的activity是密切相關的。
如果activity是暫停狀态,其中所有的fragment都是暫停狀态;如果activity是stopped狀态,這個activity中所有的fragment都不能被啟動;如果activity被銷毀,那麼它其中的所有fragment都會被銷毀。
但是,當activity在活動狀态,可以獨立控制fragment的狀态,比如加上或者移除fragment。
當這樣進行fragment transaction(轉換)的時候,可以把fragment放入activity的back stack中,這樣使用者就可以進行傳回操作。
使用fragment時,需要繼承fragment或者fragment的子類(dialogfragment, listfragment, preferencefragment, webviewfragment),是以fragment的代碼看起來和activity的類似。
每當建立一個fragment時,首先添加以下三個回調方法:
oncreate():系統在建立fragment的時候調用這個方法,這裡應該初始化相關的元件,一些即便是被暫停或者被停止時依然需要保留的東西。
oncreateview():當第一次繪制fragment的ui時系統調用這個方法,該方法将傳回一個view,如果fragment不提供ui也可以傳回null。注意,如果繼承自listfragment,oncreateview()預設的實作會傳回一個listview,是以不用自己實作。
onpause():當使用者離開fragment時第一個調用這個方法,需要送出一些變化,因為使用者很可能不再傳回來。
将fragment加載到activity當中有兩種方式:
方式一:添加fragment到activity的布局檔案當中
方式二:在activity的代碼中動态添加fragment(薦)
第一種方式雖然簡單但靈活性不夠。添加fragment到activity的布局檔案當中,就等同于将fragment及其視圖與activity的視圖綁定在一起,且在activity的生命周期過程中,無法切換fragment視圖。
第二種方式比較複雜,但也是唯一一種可以在運作時控制fragment的方式(加載、移除、替換)。
二、fragment的生命周期詳解:
先來看一下官方文檔的圖檔吧:

我們再把activity的生命周期和fragment的生命周期對比一下,就清楚很多了:
我們還是在執行個體中來看一下fragment的生命周期吧。
【執行個體】在mainactivity中加載一個fragment:(完整版代碼如下)
我們所建立的fragment的布局檔案fragment01.xml的代碼如下:
myfragment.java代碼如下:(注意生命周期中每個方法的作用)
activity_main.xml的代碼如下:
mainactivity.java的代碼如下:
可以看到,上面的代碼在每個生命周期的方法裡都列印了日志,然後我們來運作一下程式,可以看到列印日志如下:
初次加載:(分成兩部分來看)
點選一下home鍵(或接入電話),列印日志如下:
重新進入進入程式(或電話結束),列印日志如下:
點選back鍵退出程式,列印日志如下:
通過上面的日志,我們能夠看出,fragment和activity的生命周期太相似了。隻是有幾個activity中沒有的新方法,需要重點介紹一下:
onattach方法:fragment和activity建立關聯的時候調用(獲得activity的傳遞的值)
oncreateview方法:為fragment建立視圖(加載布局)時調用(給目前的fragment繪制ui布局,可以使用線程更新ui)
onactivitycreated方法:當activity中的oncreate方法執行完後調用(表示activity執行oncreate方法完成了的時候會調用此方法)
ondestroyview方法:fragment中的布局被移除時調用(表示fragment銷毀相關聯的ui布局)
ondetach方法:fragment和activity解除關聯的時候調用(脫離activity)
三、fragment傳回棧的管理:
将fragment添加到傳回棧中:
假設現在我們有兩個fragment:fragment01和fragment02,我們現在從fragment01的界面跳到fragment02,然後按back鍵,發現程式是直接退出了,而不是傳回到fragment01。如果現在想實作以下功能:從fragment01的界面跳到fragment02,然後按back鍵,會傳回到fragment01。這個功能該怎麼實作呢?這其實就利用到了傳回棧的知識。
其實很簡單,fragmenttransaction中提供了一個addtobackstack()方法,可以将一個事務添加到傳回棧中。
我們先回顧一下之前動态加載fragment的代碼,然後在此基礎之上,增加一行代碼就可以将fragment添加到傳回棧中:(即第07行代碼)
第07行代碼:我們在事務送出之前調用了fragmenttransaction的addtobackstack()方法,它可以接受一個名字用于描述傳回棧的狀态,,一般傳入null即可。
【執行個體】現在通過代碼來實作以下界面(下面的圖檔為程式運作時加載的首頁),并且把每一個fragment都加入到傳回棧當中去,然後觀察其生命周期的變化。完整代碼如下:
首先建立工程檔案m01_fragment04,然後開始我們的代碼之旅:
我們先把右側的四個fragment建起來吧:
fragment01.java主要部分的代碼如下:
為避免啰嗦,這裡就不把fragment01生命周期中的其他函數羅列出來了,我們隻要知道在實際代碼中這些函數都是加了的。
fragment01的布局檔案f1.xml的代碼如下:
然後依次建立出fragment02、fragment03、fragment04的java代碼和布局檔案。
mainactivity的布局檔案activity_main.xml代碼如下:
其中,第一個linearlayout表示左側的按鈕,第二個linearlayout留給右邊的fragment。
上當代碼中,通過點選不同的按鈕,就能跳到對應的fragment,而這四個fragment都已經加入到了傳回棧當中。運作程式之後,也是這樣的。
注意第46行和第72行,transaction = manager.begintransaction()意味着開始,transaction.commit()意味着結束。
我們就其中的fragment01和fragment02來讨論一下他們的生命周期的變化:
運作程式後,界面如下,沒有任何fragment被加載:
點選左側第一個按鈕,加載fragment01:
點選左側第二個按鈕,加載fragment02(此時fragment01被替換,并被壓到了棧當中):
注:如果fragment01在替換的時候沒有被壓到棧中,那就會被銷毀,在執行完ondestroyview()方法後,會繼續執行ondestroy()和ondetach()方法。
按back鍵,fragment01重新傳回到螢幕:(fragment02被銷毀)
再按back鍵,fragment01被銷毀:
注:fragment的傳回棧由activity管理;而activity的傳回棧由系統管理。