Fragment中呼叫getActivity為null的問題
很多人都曾被這個問題所困擾,如果app長時間在後臺執行,再次進入app的時候可能會出現crash,而且fragment會有重疊現象。如果系統記憶體不足、切換橫豎屏、app長時間在後臺執行,Activity都可能會被系統回收然後重建,但Fragment並不會隨著Activity的回收而被回收,建立的所有Fragment會被儲存到Bundle裡面,
下面是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;
}
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()方法,會報空指標異常
對於上面的問題,可以考慮下面這兩種解決辦法:
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);
}