Android中AbsSavedState$1转CompoundButton$SavedState异常排查求助
这个异常的核心是View状态恢复时的类型不匹配——系统在重启应用恢复界面状态时,会根据View的ID去匹配对应的SavedState实现类,如果ID对应的View类型在重启前后发生了变化,或者存在ID冲突导致状态混淆,就会抛出这个转换异常。结合你描述的场景(Alarm重启应用、崩溃在LauncherActivity onCreate前、未直接使用CompoundButton),可能的原因有这些:
隐性使用CompoundButton子类但存在ID冲突:你没直接写
CompoundButton,但布局里大概率用了Switch、CheckBox、ToggleButton这类继承自它的控件。如果这些控件的ID,曾经被用于其他非CompoundButton类型的View(比如旧版本代码、其他布局文件),当Alarm触发应用重启时,系统会尝试用之前缓存的CompoundButton状态去恢复当前的View,就会触发类型转换失败。系统状态缓存残留:通过Alarm重启属于进程被杀后的冷启动,系统会保留之前的View状态缓存。如果你的应用最近修改过某个View的类型但没改ID(比如把一个TextView改成了Switch,或者反过来),旧的状态缓存和当前View类型不匹配,就会在恢复状态时崩溃。
第三方库ID冲突:虽然你排查了自己的
values/ids.xml,但引入的第三方库可能定义了和你布局中View相同的ID,而那个库中该ID对应的是CompoundButton类型。重启时系统混淆了不同模块的ID对应的状态,导致异常。自定义View的SavedState实现错误:如果你的项目里有自定义View,它的SavedState没有正确继承
View.BaseSavedState,或者在onSaveInstanceState/onRestoreInstanceState方法中逻辑有误,可能会被系统误判为CompoundButton的状态类型,进而触发转换异常。
排查建议:
- 检查LauncherActivity的布局(包括所有被
include的子布局),找出所有Switch、CheckBox等CompoundButton子类控件,记录它们的ID,然后排查这些ID是否在其他布局/旧代码中被用于非CompoundButton类型的View。 - 临时修改这些控件的ID,再用Alarm重启应用,如果崩溃消失,就确认是ID对应的状态缓存冲突问题。
- 回顾最近的代码变更,看看有没有修改过View的类型或ID,尤其是LauncherActivity布局内的控件。
- 排查第三方库的资源ID,看看是否存在与你布局中ID重复的情况。
内容的提问来源于stack exchange,提问作者Ognjen Galić

