執行個體探究Android應用編寫時Fragment的生命週期問題_Android

來源:互聯網
上載者:User

管理fragment的生命週期有些像管理activity的生命週期。Fragment可以生存在三種狀態:

Resumed:

Fragment在一個運行中的activity中並且可見。

Paused:

另一個activity處於最頂層,但是fragment所在的activity並沒有被完全覆蓋(頂層的activity是半透明的或不佔據整個螢幕)。

Stoped:

Fragment不可見。可能是它所在的activity處於stoped狀態或是fragment被刪除並添加到後退棧中了。此狀態的fragment仍然存在於記憶體中。

同樣類似於activity,你可以把fragment的狀態儲存在一個Bundle中,在activity被recreated時就需用到這個東西。你可以在onSaveInstanceState()方法中儲存狀態並在onCreate()或onCreateView()或onActivityCreated()中恢複。

Fragment與Activity的生命週期中最大的不同就是儲存到後退棧中的過程。Activity是在停止時自動被系統壓入停止棧,並且這個棧是被系統管理的;而fragment是被壓入activity所管理的一個後退棧,並且只有你在刪除fragment後並明確調用addToBackStack()方法時才被壓入。

然而,管理fragment的生命週期與管理activity的生命週期極其相似。你所需要去思考的是activity的生命週期如何影響fragment的生命週期。


下面這張Fragment生命週期圖大家應該看得很多了:

但最近在寫PageManager(管理頁面跳轉),發現切換頁面時,之前的頁面走完onDestoryView就直接onDestory了,回來又重新onCreate,如果用hide和show的方式,都不走生命週期,看了ApiDemo代碼,發現原因,整理一下.
切換Fragment有兩種方式,一種是add新的,並把舊的hide,另一種是replace.
舊的Fragment為Fragment1,新的是Fragment2,忽略非關鍵生命週期。

使用add方法切換時:
載入Fragment1

Fragment1 onCreateFragment1 onCreateViewFragment1 onStartFragment1 onResume

用以下代碼切到Fragment2:

FragmentTransaction ft = getFragmentManager().beginTransaction();ft.hide(Fragment1);ft.add(R.id.simple_fragment, Fragment2);ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);ft.commit();

Fragment1不走任何生命週期,但會調onHiddenChanged方法

Fragment2 onCreateFragment2 onCreateViewFragment2 onStartFragment2 onResume

回到Fragment1,Remove Fragment2:

FragmentTransaction ft = getFragmentManager().beginTransaction();ft.remove(Fragment2);ft.show(Fragment1);ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);ft.commit();

Fragment1還是不走任何生命週期,調onHiddenChanged方法

Fragment2 onPauseFragment2 onStopFragment2 onDestoryViewFragment2 onDestory

用這種方法切換,Fragment在隱藏時並不會走onDestoryView,所以顯示時也不會走onCreateView,所有View都一直儲存在記憶體中。
用replace方法:
載入Fragment1生命週期與上面相同:

Fragment1 onCreateFragment1 onCreateViewFragment1 onStartFragment1 onResume

切到Fragment2:

FragmentTransaction ft = getFragmentManager().beginTransaction();ft.replace(R.id.simple_fragment, Fragment2);ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);ft.commit();

這次的Fragment1走生命週期了

Fragment1 onPauseFragment1 onStopFragment1 onDestoryViewFragment1 onDestoryFragment2 onCreateFragment2 onCreateViewFragment2 onStartFragment2 onResume

真實列印出來可能是Fragment1和Fragment2混在一起的,可以看到,Fragment1走了onDestory,被完全回收了!
再切回到Fragment1

FragmentTransaction ft = getFragmentManager().beginTransaction();ft.replace(R.id.simple_fragment, Fragment1);ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);ft.commit();
Fragment1 onCreateFragment1 onCreateViewFragment1 onStartFragment1 onResumeFragment2 onPauseFragment2 onStopFragment2 onDestoryViewFragment2 onDestory

Fragment1因為已經被回收,又走onCreate,Fragment2被回收。

這兩種方式顯然都不滿足我的需求,且與生命週期圖不同。因為我需要在使用者看見/看不見Fragment時register和unregister BroadcastReceiver之類的東西(onHiddenChanged也能實現,但第一次載入顯示,以及銷毀時不會走onHiddenChanged方法),也不希望使用者回到上一個Fragment就重新建立整個Fragment,因為這樣消耗資源。

看了ApiDemo,發現也是用replace方法,但是,我少了一行:

ft.addToBackStack(null);

在replace時加上這行,可以把原來的Fragment放入棧中,走onDestoryView方法,但不會onDestory,返回時,直接onCreateView,不再onCreate.
返回直接調用popBackStack()方法:

getFragmentManager().popBackStack();

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.