一个关于Fragment的Bug的定位与总结

来源:互联网 发布:知否的人物关系图 编辑:程序博客网 时间:2024/04/30 11:26

原文地址

这是一个之前在开发工作中遇到的Bug,排查定位了很久,觉得有必要记录一下。

故事背景:我们的Android程序M运行在定制的Android系统上,在客户交付现场演示时用的是VPN网络,当VPN断开时,问题出现了,操作系统会将我们的程序M切到后台。

问题应该从两方面去定位,首先是这个定制的Android系统,为什么在非VPN网络下使用正常,而在VPN网络下便会出现这个Bug;接着就是我们的应用程序M,接下来的分析都是在这个层面上展开的。

先从问题的现象及解决的思路开始。

BUG现象:VPN断开之后,操作系统将M切到后台,M的MainActivity执行生命周期onPause()-onShop()-onDestroy()退出,未调用finish(),为非正常退出。退出后M由于程序中异常捕捉部分的代码的缘故会重新启动回到前台,此时程序直接进入MainActivity(未经过欢迎页面),之后程序便僵死,报Fragment重复添加到父View的错误。

解决方法:通过打印log日志定位,判断问题产生的原因是当M被切到后台时当前处于哪个Fragment页面下,那么该Fragment就没有被它的父View移除,这就导致程序重新起来后报Fragment重复添加到父View的错误,解决办法是在所有FragmentonDestroy()方法中将它从父View移除;

通过上述方法处理完之后暴露出了新的问题,M重新起来后没有僵死而是直接闪退,报MainActivity视图监视器方法中出现空指针的错误。通过打印log日志,发现程序中Fragment生命周期的执行快于MainActivity生命周期的执行,通过分析,最后发现是由FragmentManager引起的,FragmentManager对象从系统中获取,它是Fragment的管理器, Fragment的回收与否,是由FragmentManager来控制的,而M在VPN断开被切到后台时FragmentManager并没有将它管理的Fragment移除,这就导致M重回前台时在onCreate()方法中调用父类时FragmentManager就将它保留着的Fragment初始化完了,那么后续重新创建的Fragment在被添加到ViewPager中的时候FragmentManager并没有将它们再次初始化,导致它们的组件均为空,这就是空指针产生的原因,解决方法是在继承FragmentManager的内部类中创建一个removeAllFragment()的方法,在MainActivityonDestroy()中调用,使M在退出时立即执行事务将FragmentFragmentManager中移除;

通过上述方法的处理,M重回前台之后就没有退出了,界面显示正常,但是大部分功能无法正常使用,原因是程序中存在大量保存系统状态的static静态变量,M在异常退出后重回前台时这些静态变量没有被重新初始化,扰乱了系统功能,这是历史遗留问题,由于修改起来工作量比较大,问题暂且搁置。

通过这次Debug,我发现自己思考问题的模式有很大的缺陷,分析问题时总是停留在猜测阶段,“我觉得……”,“这个可能是……”,经常讲出一些不确定的话,严重影响到问题的解决。这种思维方式无法引导我主动去找寻问题产生的根源,只是通过表象去揣测,去猜,当然,这是无法解决问题的。当问题产生的时候,我们应该通过分析去理清楚哪个部分是确定的,无需去再去确认,哪部分是模糊的,不确定的,带着疑问的,然后全力去分析和确认这一部分,不断缩小问题的范围,直至最终解决问题。脑子混混沌沌的人,做什么都会事倍功半,醒来吧,骚年。

1 0
原创粉丝点击