ViewPager+Fragment 销毁重建问题

问题描述

页面销毁重建后,activity点击调用fragment的方法。使用List保存的引用调用,出现了崩溃 (此时的fragment没有走onCreateView等生命周期方法,不能拿来用)。

问题分析

List 保存的值 与 真实展示的fragment不对应,因为fragment销毁重建实际展示的fragment并不是list保存的,直接使用会出错。

原因
FragmentPagerAdapter 在重建后instantiateItem 并不是使用新建,而是从 FragmentManager 查找,使用查找到的进行展示。

fragment消耗重建没有反应到List中。这种场景可以从childFragmentManager中取值,重新更新list

解决

方式一 销毁重建场景在onCreate清理掉原有的fragments

private void clearFragments(){
        FragmentManager fm = getChildFragmentManager();
        if(fm != null && fm.getFragments() != null && fm.getFragments().size() > 0){
            FragmentTransaction ft = fm.beginTransaction();
            for(Fragment fragment : fm.getFragments()){
                ft.remove(fragment);
            }
            ft.commit();
        }
}

方式二 销毁重建后同步本地List

override fun onViewStateRestored(savedInstanceState: Bundle?) {
        super.onViewStateRestored(savedInstanceState)
        if (savedInstanceState != null) {
        	//销毁重建场景
            val normalFragmentAdapter = mBinding.viewPager.adapter as NormalFragmentAdapter
            for (index in fragments.indices) restoreFragment(index, normalFragmentAdapter)
        }
    }

    private fun restoreFragment(position: Int, adapter: NormalFragmentAdapter) {
        val fragment = childFragmentManager.findFragmentByTag(
            adapter.makeFragmentName(mBinding.viewPager.id, position.toLong())
        )
        if (fragment != null) fragments[position] = fragment
    }

NormalFragmentAdapter添加这个方法

fun makeFragmentName(viewId: Int, id: Long): String {
        return "android:switcher:$viewId:$id"
    }

参考资料

Activity被销毁重建后,Fragment异常
记一个ViewPager+Fragment的意外销毁重建的崩溃问题

你可能感兴趣的:(ViewPager,Android,Fragment)