遇到的场景
activity内一个viewpager包含三个fragment,都是通过new fragment()后add到pageradater中:
pages = new ArrayList<>();
productPage = new CategoryItemDetailFragment();
pages.add(productPage);
detailPage = new ItemDetailPageFregment();
detailPage.setHostActivity(this);
pages.add(detailPage);
specPage = new ItemSpecFragment();
specPage.setHostActivity(this);
pages.add(specPage);
pagerAdapter = new FragAdapter(getSupportFragmentManager(),pages);
当app crash后,该activity试图恢复,界面都正常显示,但是点击某些按钮无反应,调试得知:
fragment.getActivity()为null
fragment中的所有view对象都为null
fragment中的成员变量很多为null.
原因:
app crash时,fragment状态自动保存
重新恢复时,自动恢复原原来的三个fragment,但同时,activity的oncreate方法也走了,上述的viewpager初始化代码运行,又new了三个fragment.而且,恢复的fragment刚好盖在new出来的fragment上面.点击界面按钮,事件被恢复的fragment捕获,代码运行在此对象中,所以看到的很多东西都为null.
可以看到FragmentActivity中保存fragment状态的代码:
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
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);
}
}
https://blog.csdn.net/c10wtiybq1ye3/article/details/78098520
https://juejin.im/post/5a2e4c825188257df846206c
解决办法:
复写宿主activity的onSaveInstanceState(Bundle outState),不调用super.onSaveInstanceState(outState)
@Override
protected void onSaveInstanceState(Bundle outState) {
//super.onSaveInstanceState(outState);
}
但这还会存在一个问题:
一些恢复时必须的字段无法保存,比如开启这个activity的intent传入的用于初始化的字段.
而实际测试过程中,activity正常恢复了,很奇怪...什么原因呢?
参考:
关于Activity被回收,Fragment还在的问题