Android清理Fragment回退栈搭配共享元素时偶发NullPointerException问题
问题原因
本次崩溃是androidx fragment库的已知缺陷,触发逻辑如下:
- 崩溃点位于
FragmentTransition.captureInSharedElements方法中,框架尝试读取共享元素列表的size时,该列表已被置空触发空指针 - 你开启了事务的
setReorderingAllowed(true)配置,且跳转链路中存在多个携带共享元素的回退栈记录 - 当你调用
popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)一次性清空所有回退栈时,FragmentManager需要逆向执行所有事务的退出过渡动画,但中间状态的Fragment已被提前销毁,对应的共享元素集合没有被正确初始化就被访问,最终触发偶现空指针。该问题在1.3.0及更老版本的fragment库中普遍存在。
解决方案
你可以根据项目情况选择以下任意一种方案修复:
- 方案1:升级fragment依赖版本
该问题官方已在androidx fragment 1.4.0及以上版本修复,直接将依赖版本升级到1.4.0以上即可从根源解决问题。 - 方案2:回退前临时禁用共享元素过渡
如果你暂时无法升级依赖,可以在批量回退前清空当前Fragment的共享元素过渡配置,绕开动画逻辑:Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_holder); if (currentFragment != null) { currentFragment.setSharedElementReturnTransition(null); currentFragment.setSharedElementReenterTransition(null); } getSupportFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); - 方案3:用replace事务直接切回根Fragment,绕开回退动画
不使用批量pop回退栈的逻辑,直接执行replace事务切换回Fragment A,再清空回退栈,完全避开回退动画的处理链路:getSupportFragmentManager().beginTransaction() .replace(R.id.fragment_holder, A.newInstance(), A_TAG) .setReorderingAllowed(true) .commit(); getSupportFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
内容的提问来源于stack exchange,提问作者Soheil
相关产品推荐
相关产品推荐

