2017-10-17 | work

android:configChanges 的一个坑

昨天下午收到一个 bug,开机时出现并且偶现…我现在一看到偶现就头疼,维护别人的代码真的好痛苦,哈哈。

bug 具体表现为清除所有应用数据后重新启动设备,使用语音控制打开应用,应用 Activity 界面正常显示后再次变为加载状态,一台设备出现,另有一台不会。

问题其实很简单,而且很低级。可是我困在上面的几个干扰里面很久,清除数据和重启实际上不是问题出现的原因。重点就在这个开机部分和启动 Activity 的逻辑中。

产品需求上整个界面只会在第一次启动时 loading 数据,之后都不会 showLoading()。出于未知原因,Activity 被重新创建,又跑了一遍 Activity 的生命周期。然而这第二次启动和第一次启动时的应用状态可不一样了(第一次启动时,负责启动的 Service 还会进行额外的工作),导致只显示 loading 不会执行到 dismissLoading() 代码。

所以,是什么导致的 Activity 被重建呢?向达哥请教之后,达哥果然是老司机!原因是设备开机后立即打开应用,这时 Activity 接收到 sim 卡状态更新信息的消息触发了上述逻辑。另一台设备不能复现的原因是它没插 sim 卡…….

我们再看一下 Activity 配置项里的 android:configChanges

列出 Activity 将自行处理的配置更改。在运行时发生配置更改时,默认情况下会关闭 Activity 然后将其重新启动,但使用该属性声明配置将阻止 Activity 重新启动。 Activity 反而会保持运行状态,并且系统会调用其 onConfigurationChanged() 方法。

其中有可配置项

说明
mcc IMSI 移动国家/地区代码 (MCC) 发生了变化 - 检测到了 SIM 并更新了 MCC。
mnc IMSI 移动网络代码 (MNC) 发生了变化 - 检测到了 SIM 并更新了 MNC。

也就是说 Activity 默认收到 sim 卡状态信息改变后会重新创建 Activity,我们只要在 AndroidManifest 里忽略掉这些项即可,这样信息变更的操作将会交由 onConfigChanged() 处理,和转屏重建的原理是一致的。相对于屏幕旋转来说,android:configChanges 的其他值还是很陌生的,但是以后遇到 Activity 莫名其妙重建的话,一定要检查这个位置。

Ref