Fragment生命周期详解
關于Fragment的生命周期,博主寫過Activity與Fragment生命周期詳解,基本上把Fragment的生命周期詳細介紹過,但是那僅僅是創建一個Fragmnet時的生命周期,而事實上Fragment的出現是為了動態的切換顯示不同的界面的,因此我們對于Fragment的生命周期的了解不能僅僅停留在創建一個Fragment的時候,而是應該能夠知道調用不同API切換Fragment時的生命周期是怎么的,如調用add(),hide(),show()與replace()時它們的生命周期的不同,博主在昨天360視頻面試的時候就被問到過。
一使用靜態方式時的生命周期:
正如我們在Activity與Fragment生命周期詳解中所介紹的,此時Fragment的生命周期為
onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume, onPause, onStop, onDestroyView, onDestroy, onDetach.
可以參看Activity與Fragment生命周期詳解中相關內容的官方圖片理解,
1其中當創建一個Fragment首次展示其布局界面時:
onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment處于運行狀態
2當關閉手機屏幕或者手機屏幕變暗或直接按home鍵返回桌面時,其生命周期方法調用的順序是
onPause, onStop
3當再次對手機屏幕解鎖或者手機屏幕變亮時,其生命周期方法調用的順序:
onStart, onResume
4當對Fragment按返回鍵時:
onPause, onStop, onDestroyView, onDestroy, onDetach.
二使用FragmentManager動態的添加Fragment
這塊是本博客講解的重點,因為動態添加涉及到Fragment的切換,所以我們先定義兩個Fragment。代碼如下:
public class FragOne extends Fragment {private static final String TAG = FragOne.class.getSimpleName();@Overridepublic void onAttach(Activity activity) {super.onAttach(activity);Log.i(TAG, "onAttach");}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Log.i(TAG, "onCreate");}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {Log.i(TAG, "onCreateView");return inflater.inflate(R.layout.fragment_test_a, null, false);}@Overridepublic void onViewCreated(View view, Bundle savedInstanceState) {Log.i(TAG, "onViewCreated");super.onViewCreated(view, savedInstanceState);}@Overridepublic void onDestroy() {Log.i(TAG, "onDestroy");super.onDestroy();}@Overridepublic void onDetach() {Log.i(TAG, "onDetach");super.onDetach();}@Overridepublic void onDestroyView() {Log.i(TAG, "onDestroyView");super.onDestroyView();}@Overridepublic void onStart() {Log.i(TAG, "onStart");super.onStart();}@Overridepublic void onStop() {Log.i(TAG, "onStop");super.onStop();}@Overridepublic void onResume() {Log.i(TAG, "onResume");super.onResume();}@Overridepublic void onPause() {Log.i(TAG, "onPause");super.onPause();}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {Log.i(TAG, "onActivityCreated");super.onActivityCreated(savedInstanceState);} }第二個Fragment public class FragTwo extends Fragment {private static final String TAG = FragTwo.class.getSimpleName();@Overridepublic void onAttach(Activity activity) {super.onAttach(activity);Log.i(TAG, "onAttach");}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Log.i(TAG, "onCreate");}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {Log.i(TAG, "onCreateView");return inflater.inflate(R.layout.fragment_test_b, null, false);}@Overridepublic void onViewCreated(View view, Bundle savedInstanceState) {Log.i(TAG, "onViewCreated");super.onViewCreated(view, savedInstanceState);}@Overridepublic void onDestroy() {Log.i(TAG, "onDestroy");super.onDestroy();}@Overridepublic void onDetach() {Log.i(TAG, "onDetach");super.onDetach();}@Overridepublic void onDestroyView() {Log.i(TAG, "onDestroyView");super.onDestroyView();}@Overridepublic void onStart() {Log.i(TAG, "onStart");super.onStart();}@Overridepublic void onStop() {Log.i(TAG, "onStop");super.onStop();}@Overridepublic void onResume() {Log.i(TAG, "onResume");super.onResume();}@Overridepublic void onPause() {Log.i(TAG, "onPause");super.onPause();}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {Log.i(TAG, "onActivityCreated");super.onActivityCreated(savedInstanceState);} }可以看到這兩個Fragment的代碼基本上完全相同,都是重寫了Fragment中相關的生命周期函數。一當沒使用addToBackStack函數時。
1使用replace()函數時:
當我們使用replace初次顯示一個Fragment時,此時代碼如下:
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();fragOne = new FragOne();fragmentTransaction.replace(R.id.frag_container, fragOne, fragNames[0]);fragmentTransaction.commit();此時的生命周期和上述講述的完全相同,即onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment處于運行狀態。當我們使用replace()來替換一個已經存在的Fragment時(如騰訊QQ中當我們點擊不同的底部按鈕時會替換之前的Fragment),此時代碼如下:
public void onClick(View v) {FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();switch (v.getId()) {case R.id.button1:if (fragOne == null) {fragOne = new FragOne();fragmentTransaction.replace(R.id.frag_container, fragOne, fragNames[0]); // fragmentTransaction.addToBackStack(fragNames[0]);} else {Fragment fragment = fragmentManager.findFragmentByTag(fragNames[0]);fragmentTransaction.replace(R.id.frag_container, fragment, fragNames[0]);}break;case R.id.button2:if (fragTwo == null) {fragTwo = new FragTwo();fragmentTransaction.replace(R.id.frag_container, fragTwo, fragNames[1]); // fragmentTransaction.addToBackStack(fragNames[1]);} else {Fragment fragment = fragmentManager.findFragmentByTag(fragNames[1]);fragmentTransaction.replace(R.id.frag_container, fragment, fragNames[1]);}break;default:break;}fragmentTransaction.commit();}可以看到在上述代碼中,我們將addToBackStack函數的調用注釋起來,表示此時不適用該功能。此時的運行順序為:
可以看到第一個Fragment的調用順序為:onPause, onStop, onDestroyView, onDestroy, onDetach,這表明fragOne已經被FragmentManager銷毀了,取而代之的是第二個Fragment,這也與replace()函數的名稱和不適用addToBackStack相符合(即替換且不添加到Fragment返回棧中,既然是替換當然得去除前一個,添加第二個Fragment)
這說明,在使用replace添加Fragment時如果沒有調用addToBackStack方式的話,當FragmentManager替換Fragment時,是不保存Fragment的狀態的,此時第二個Fragment將會直接替換前一個Fragment。
二使用addToBackStack函數時。
當我們使用replace函數且設置addToBackStack函數初次顯示一個Fragment運行結果為:onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment處于運行狀態。即與不使用addToBackStack函數時的運行結果相同。
當我們使用replace函數且設置addToBackStack函數來替換之前顯示的Fragmen't時運行結果為:
可以看到與之前的不使用addToBackStack相比,fragTwo的生命周期不受影響,而fragOne的生命周期和不使用addBackToStack函數相比,只存在三種狀態的切換:onPause
onStop,onDestroyView。前者很好理解,因為addToBackStack函數顧名思義就是添加到回退棧中的意思,即當一個Fragment被另一個Fragment替換時會將之前的添加到回退棧中,因此也很好理解fragTwo的生命周期不受影響,因為是將被替換的添加到回退棧中,所以替換者不受影響。另外fragOne狀態只到達onDestroyView,而無onDestroy,
onDetach。這說明fragOne僅僅只是界面被銷毀onDestroyView,而fragOne對象的實例依然被保存在FragmentManager中(因為無onDestroy,onDetach),它的部分狀態依然被保存在FragmentManager中。我們可以來驗證一下:
我們點擊按鈕切換,讓fragOne來替換當前顯示的fragTwo,此時運行結果如下:
可以看到此時運行結果與fragTwo替換fragOne時fragOne的生命周期調用順序非常相似,而且可以看到fragOne的生命周期是直接從onCreateView開始的,這也剛好對應上面的fragOne被fragTwo替換時生命周期到達onDestroyView,即之前的fragOne僅僅銷毀了視圖,而fragOne對象的實例依然被保存在FragmentManager中,所以此時只需要創建視圖,即直接從onCreateView開始。
三使用show()/hide()函數時:首先要明白使用show()/hide()時一般是會使用addToBackStack,,因為要使用show()/hide()前提是該Fragment實例已經存在,只不過我們是否將其界面顯示出來而已,因此我們需要使用addToBackStack函數將一個Fragment的實例對象保存在Fragment的回退棧中。此時代碼如下:
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();switch (v.getId()) {case R.id.button1:hideAllFrags(fragmentTransaction);if (fragA == null) {fragOne = new FragOne();fragmentTransaction.add(R.id.frag_container, fragOne, fragNames[0]);fragmentTransaction.addToBackStack(fragNames[0]);} else {fragmentTransaction.show(fragOne);}break;case R.id.button2:hideAllFrags(fragmentTransaction);if (fragTwo == null) {fragTwo = new FragTwo();fragmentTransaction.add(R.id.frag_container, fragTwo, fragNames[1]);fragmentTransaction.addToBackStack(fragNames[1]);} else {fragmentTransaction.show(fragTwo);}break;default:break;} fragmentTransaction.commit();當我們使用add()/show()函數初次顯示一個Fragment運行結果為:onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment處于運行狀態。這個很好理解,不再贅述。
當我們點擊按鈕切換顯示第二個Fragment時運行結果為:
可以看到此時fragOne無輸出,表示fragOne的生命周期不受影響,而fragTwo的輸出結果與直接初次顯示fragTwo時是一樣的。其實這也很好理解因為在add()/show()/hide()顧名思義就是添加顯示隱藏的意思,它都不會對另外的Fragment的生命周期起作用。
轉載于:https://www.cnblogs.com/hainange/p/6334027.html
總結
以上是生活随笔為你收集整理的Fragment生命周期详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库,唯一索引,重复数据处理
- 下一篇: 一个App完成入门篇(一)-从Hello