Android應用開發:Fragment的非中斷保存setRetaineInstance

引言

首先,要明確什麼叫「非中斷保存」。熟悉Fragment的開發人員都知道,Fragment是依附於Activity的。當Activity銷燬時,Fragment會隨之銷燬。而當Activity配置發生改變(如屏幕旋轉)時候,舊的Activity會被銷燬,而後從新生成一個新屏幕旋轉狀態下的Activity,天然而然的Fragment也會隨之銷燬後從新生成,而新生成的Fragment中的各個對象也與以前的那個Fragment不同,伴隨着他們的動做、事件也都不同。因此,這時候若是想保持原來的Fragment中的一些對象,或者想保持他們的動做不被中斷的話,就迫切的須要將原來的Fragment進行非中斷式的保存。 java

生命週期

Activity的生命週期在配置發生改變時: android

 
  1. onPuase->onStop->onDestroy->onStart->onResume

好比在Activity中發生屏幕旋轉,其生命週期就是如此。而在onDestroy中,Activity會將其FragmentManager所包含的Fragment都銷燬掉(默認狀態),即Fragment的生命週期爲: git

 
  1. onDestroyView->onDestroy->onDetach

經過查看FragmentManager.java的代碼,能夠發如今Fragment生命週期執行到onDestroyView時候,狀態會由正常的ACTIVITY_CREATED變爲CREATED。而到了onDestroy生命週期時候,執行的代碼出現了有意思的事情: github

 
  1. if (!f.mRetaining) {
  2. f.performDestroy();
  3. }
  4. f.mCalled = false;
  5. f.onDetach();
  6. if (!f.mCalled) {
  7. throw new SuperNotCalledException("Fragment " + f
  8. + " did not call through to super.onDetach()");
  9. }
  10. if (!keepActive) {
  11. if (!f.mRetaining) {
  12. makeInactive(f);
  13. } else {
  14. f.mActivity = null;
  15. f.mParentFragment = null;
  16. f.mFragmentManager = null;
  17. }
  18. }
  19. 來源: <https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/FragmentManager.java>

當Fragment的mRetaining被置true的時候,Destroy生命週期並不會執行,而Fragment的mRetaining狀態是經過其retainNonConfig()來配置的,配置條件是Fragment不爲空且Framgnet的mRetainInstance爲true。到這裏就能看到,若是想要本身的Fragment不被銷燬掉,就要讓這個mRetainInstance爲true。 app

經過查閱Fragment.java源碼發現,經過API setRetainInstance和getRetainInstance能夠對其進行操做。一樣,Android文檔中對這兩個接口也有了必定的描述。 spa

總結

這裏結合Fragment.java中setRetainInstance的註釋進行一下Fragment非中斷保存的總結。原註釋以下: code

 
  1. /**
  2. * Control whether a fragment instance is retained across Activity
  3. * re-creation (such as from a configuration change). This can only
  4. * be used with fragments not in the back stack. If set, the fragment
  5. * lifecycle will be slightly different when an activity is recreated:
  6. * <ul>
  7. * <li> {@link #onDestroy()} will not be called (but {@link #onDetach()} still
  8. * will be, because the fragment is being detached from its current activity).
  9. * <li> {@link #onCreate(Bundle)} will not be called since the fragment
  10. * is not being re-created.
  11. * <li> {@link #onAttach(Activity)} and {@link #onActivityCreated(Bundle)} <b>will</b>
  12. * still be called.
  13. * </ul>
  14. */
  15. public void setRetainInstance(boolean retain) {
  16. if (retain && mParentFragment != null) {
  17. throw new IllegalStateException(
  18. "Can't retain fragements that are nested in other fragments");
  19. }
  20. mRetainInstance = retain;
  21. }

若是想叫本身的Fragment即便在其Activity重作時也不進行銷燬那麼就要設置setRetainInstance(true)。進行了這樣的操做後,一旦發生Activity重組現象,Fragment會跳過onDestroy直接進行onDetach(界面消失、對象還在),而Framgnet重組時候也會跳過onCreate,而onAttach和onActivityCreated仍是會被調用。須要注意的是,要使用這種操做的Fragment不能加入backstack後退棧中。而且,被保存的Fragment實例不會保持過久,若長時間沒有容器承載它,也會被系統回收掉的。 orm

版權聲明:本文爲博主原創文章,未經博主容許不得轉載。 對象

相關文章
相關標籤/搜索