在很舊的v4包里庙睡,fragment的問題更多蝇庭,比如需要自己重寫Fragment類的onDestory梨与,不過這些都在最新的v4包里解決了,但是fragment仍然問題很多未舟,有個很常見的問題就是Activity因內(nèi)存不夠被回收以后圈暗,在FragmentActivity重啟時,F(xiàn)ragment會出一些問題裕膀,比如fragment重疊员串,或者某些fragment不顯示之類的,這種情況原因如下:
先貼兩段代碼:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getContentViewResId());
if (getIntent().hasExtra(Intent.EXTRA_TITLE)) {
setTitle(getIntent().getStringExtra(Intent.EXTRA_TITLE));
}
final String customTitle = getIntent().getStringExtra(Intent.EXTRA_TITLE);
setTitle(customTitle != null ? customTitle : getTitle());
if (savedInstanceState == null) {
mFragment = onCreatePane();
mFragment.setArguments(intentToFragmentArguments(getIntent()));
getFragmentManager().beginTransaction()
.add(R.id.root_container, mFragment, "single_pane")
.commit();
} else {
mFragment = getFragmentManager().findFragmentByTag("single_pane");
}
}
*
* Save all appropriate fragment state.
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);//這里保存了Fragment數(shù)據(jù)
}
if (mPendingFragmentActivityResults.size() > 0) {
outState.putInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG, mNextCandidateRequestIndex);
int[] requestCodes = new int[mPendingFragmentActivityResults.size()];
String[] fragmentWhos = new String[mPendingFragmentActivityResults.size()];
for (int i = 0; i < mPendingFragmentActivityResults.size(); i++) {
requestCodes[i] = mPendingFragmentActivityResults.keyAt(i);
fragmentWhos[i] = mPendingFragmentActivityResults.valueAt(i);
}
outState.putIntArray(ALLOCATED_REQUEST_INDICIES_TAG, requestCodes);
outState.putStringArray(REQUEST_FRAGMENT_WHO_TAG, fragmentWhos);
}
從源碼中得知昼扛,當(dāng)Activity調(diào)用onSaveInstanceState方法的時候寸齐,會保存當(dāng)前Activity里面的所有Fragment,保存在了一個Bundle里抄谐,key就是FRAGMENTS_TAG渺鹦。
這個Bundle會在Activity恢復(fù)的時候傳給onCreate,這就是為什么onSaveInstanceState不是null了。
如果要原樣恢復(fù)Fragment需要做的工作挺多的蛹含,需要在FragmentActivity的onCreate方法里判斷如果savedInstanceState不為空就從FragmentManager里獲取之前的實例毅厚,不過不需要再次添加到FragmentManager里了,獲取的目的是以后做什么操作還用這個獲取到的實例浦箱,雖然恢復(fù)的Fragment中的View沒問題吸耿,不過里面如果有自己的一些值并且沒有在Fragment自己的savedInstanceState方法里保存的話,恢復(fù)的fragment是沒有這些值的(如果這些值是從其他頁面通過bundle傳遞過來的那么你獲取的時候肯定是從bundle獲取這時候是有值的)酷窥,我覺得在大部分應(yīng)用里不需要這么做咽安,有兩種更簡單的解決辦法:
- 重寫FragmentActivity的onCreate方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
//刪除保存的Fragment狀態(tài)
if (savedInstanceState != null) {
//"android:support:fragments"是FragmentActivity類里的包可見的值,因為不是public的所以直接寫實際的字符串
savedInstanceState.putParcelable("android:support:fragments", null);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFragment = new onCreatePane();
getSupportFragmentManager().beginTransaction()
.add(R.id. root_container, mFragment, "single_pane")
.commit();
}
- 重寫FragmentActivity的onSaveInstanceState方法:
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
//刪除保存的Fragment狀態(tài)
outState.putParcelable("android:support:fragments", null)
}
這兩種方法任選一種都可以解決該類型的問題,第1種方法是恢復(fù)的時候清空之前的fragment蓬推。第2種方法是保存的時候直接不保存妆棒。