標籤:over port 運行 ati fragments man 代碼 res 覆蓋
在使用fragment的時候經常會遇到getActivity()為null的情況。比如我在一個非同步網路請求的回調中調用了getActivity()就會出現null 指標問題。之前解決這個問題,通常都是直接加null 指標判斷來規避,但是這並沒有真正解決問題。
很多人都曾被這個問題所困擾,如果app長時間在後台運行,再次進入app的時候可能會出現crash,而且fragment會有重疊現象。如果系統記憶體不足、切換橫豎屏、app長時間在後台運行,Activity都可能會被系統回收然後重建,但Fragment並不會隨著Activity的回收而被回收,建立的所有Fragment會被儲存到Bundle裡面,從而導致Fragment丟失對應的Activity。
下面是FragmentActivity的部分源碼
protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Parcelable p = mFragments.saveAllState(); if (p != null) { outState.putParcelable( "android:support:fragments", p); } }
如果從最近使用的應用裡面點擊我們的應用,系統會恢複之前被回收的Activity,這個時候FragmentActivity在oncreate裡面也會做Fragment的恢複,
@Override protected void onCreate(Bundle savedInstanceState) { mFragments.attachActivity(this, mContainer, null); // Old versions of the platform didn‘t do this! if (getLayoutInflater().getFactory() == null) { getLayoutInflater().setFactory(this); } super.onCreate(savedInstanceState); NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance(); if (nc != null) { mAllLoaderManagers = nc.loaders; } if (savedInstanceState != null) { Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG); mFragments.restoreAllState(p, nc != null ? nc.fragments : null); } mFragments.dispatchCreate(); }
假設我們的頁面叫MyActivity(繼承自FragmentActivity),其中用到的Fragment叫MyFragment。
出現上面這種情況時,app發生的變化如下:
1、在前面提到的幾種情況下系統回收了MyActivity
2、通過onSaveInstanceState儲存MyFragment的狀態
3、使用者再次點擊進入app
4、由於MyActivity被回收,系統會重啟MyActivity,根據之前儲存的MyFragment的狀態恢複fragment
5、MyActivity的代碼邏輯中,會再次建立新的MyFragment
6、頁面出現混亂,覆蓋了兩層的fragment。假如恢複的MyFragment使用到了getActivity()方法,會報null 指標異常
對於上面的問題,可以考慮下面這兩種解決辦法:
1、不儲存fragment的狀態:在MyActivity中重寫onSaveInstanceState方法,將super.onSaveInstanceState(outState);注釋掉,讓其不再儲存Fragment的狀態,達到fragment隨MyActivity一起銷毀的目的。
2、重建時清除已經儲存的fragment的狀態:在恢複Fragment之前把Bundle裡面的fragment狀態資料給清除。方法如下:
if(savedInstanceState!= null) { String FRAGMENTS_TAG = "Android:support:fragments"; savedInstanceState.remove(FRAGMENTS_TAG); }
Android Fragment中調用getActivity為null的問題