Galaxy A6调用单例类存储的VectorEntity对象触发空指针异常问题
问题根因
这个空指针是低内存设备上Android系统杀死应用进程后重建Activity,单例数据丢失导致的,只有Galaxy A6复现的原因也很明确:作为入门机型它的内存远小于你测试的Pixel、S系列旗舰,后台杀进程的概率高很多。
你正常跳转Activity的时候会先走赋值逻辑给ModelsProvider单例存值,但是当系统因为内存不足杀了你的进程,用户从最近任务列表恢复ColoringActivity的时候,系统会直接重建Activity,不会走之前的页面跳转逻辑,单例里存的VectorEntity也随着进程销毁被清空为null,这时候ViewModel初始化取到的自然是空对象。
你对比两个堆栈也能看出来区别:崩溃堆栈里ColoringActivity.onCreate执行到第105行就崩溃了,正常运行的堆栈里到第115行还在执行,也能说明崩溃那次是重建场景,不是正常跳转场景。
修复方案
最优方案:替换单例传参方式,用Intent传递序列化对象
Android官方本身就不推荐用单例跨页面传递数据,你可以给VectorEntity实现Parcelable接口,跳转的时候直接塞到Intent里:
@Override public void startActivity(VectorEntity selectedVectorEntity) { Intent coloringIntent = new Intent(getActivity(), ColoringActivity.class); coloringIntent.putExtra("selected_vector", selectedVectorEntity); startActivity(coloringIntent); }
之后在ColoringActivity里从Intent取出对象,再传给ViewModel即可,系统重建Activity的时候会自动保留Intent里的数据,不会丢失。
临时兼容方案:加空值判断避免崩溃
如果暂时不想改传参逻辑,可以在调用处加判空兜底:
// VectorModelContainer构造函数修改 public VectorModelContainer(VectorEntity vectorEntity) { // 空值时可以传默认值,或者提前返回结束初始化走降级逻辑 super(vectorEntity != null ? vectorEntity.getModel() : ""); this.vectorEntity = vectorEntity; init(); }
可选方案:单例加持久化缓存
如果一定要保留单例传参的逻辑,可以在ModelsProvider存值的时候同时把VectorEntity序列化后存到本地(SharedPreferences/ROOM数据库都可以),取的时候如果内存中的值为null,就从本地读取恢复。
复现方法
你可以用adb命令模拟进程杀死场景,在任意设备上复现这个问题:
- 正常进入ColoringActivity后按Home键退回桌面
- 执行adb命令杀死应用进程:
adb shell am kill com.xtremecolor.mycoloring - 从最近任务列表点开应用,就能触发崩溃
内容的提问来源于stack exchange,提问作者AtomicallyBeyond

