关于Fragment处于后台被回收后,点击重启,Fragment页面无法做任何操作
开发过程中,出现过这样一个bug,在fragment跳转到系统权限设置页面,对权限进行开关后,返回app,app白屏重新启动,fragment页面仿佛被锁死,无法进行任何操作。
项目ui架构
MainActivity
- HomeFragment
- ListFragment
- AlarmFragment
- MineFragment
操作逻辑
HomeFragment使用某个功能需要请求权限,当用户点击拒接不勾选不再提示后,当下次点击该功能时弹框提示用户跳转系统权限设置页面进行操作。(或者其它导致MainActivity处于后台被系统杀死回收的操作)
问题发现
当跳转到系统权限设置页面进行权限开关返回时,两种现象:
- App重启,重启一切正常;
- App不重启,白屏重新加载当前页面,加载完毕此
HomeFragment无法操作。百分百复现。
问题排查
怀疑是Fragment生命周期出现问题,对MainActivity设置Log打印输出。以下是App不重启时日志输出总结:
- 打印生命周期,
MainActivity重新走了onCreate()方法,参数savedInstanceState不为null。(推断App已经被系统杀死回收) - 打印
FragmentManager的getFragments()方法,输出两个HomeFragment。(问题关键点) - 打印
FragmentTransaction的getBackStackEntryCount(),输出0。 - 打印
FragmentManager的findFragmentByTag(String tag)方法,输出全为null
结论
阅读FragmentManager、FragmentStore、FragmentTransaction、BackStackRecord等系统源码,结合Activity、Fragment生命周期,Android系统回收机制等,可以得知当Activity被系统回收时,系统会将当前页面的数据保存在savedInstanceState,重新恢复时,系统会对这些对象进行恢复,但由于我们未重写数据保存和恢复的方法,所以系统恢复时并不是百分百完全复原,有些数据找不到,所以出现了add了相同的HomeFragment,而show的时候导致应该被回收的HomeFragment重叠在新add的HomeFragment上。
解决方法
最简单的方法,在MainActivity的onCreate方法中判断savedInstanceState是否为null,如果不为null,判断FragmentManager的getFragments()是否为空,不为空则将之前未销毁的fragment一个个销毁掉。
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
List<Fragment> list = fragmentManager.getFragments();
if(savedInstanceState != null && list.size() != 0){
for(Fragment fragment: list){
fragmentTransaction.remove(fragment);
fragmentTransaction.commitAllowingStateLoss();
}
}
本文探讨了在Android应用中,Fragment在后台被系统回收后,尤其是当用户从权限设置返回时遇到的无法操作问题。作者通过分析生命周期、内存管理和FragmentStore,揭示了原因并提供了在onCreate中检查并销毁多余Fragment的解决方法。
2003

被折叠的 条评论
为什么被折叠?



