app崩溃后,带fragment的activity恢复的坑

字数 326阅读 1476

遇到的场景

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还在的问题

推荐阅读更多精彩内容