开发笔记-序列化与反序列化
开发笔记主要是记录开发中遇到的一些问题和解决方案,以及引发的一些思考,不会太深入地记录问题,但是会尽可能广泛地记录涉及到的内容,方便之后整理归纳和查阅
No.1 实现 Parcelable 接口后,构造方法需要可空值
记录一下序列化遇到的问题:需要在 Intent 中传递数据,所以需要序列化,Kotlin 中实现 Parcelable 接口后,constructor(parcel: Parcel) 构造方法中报错提示需要可空值,所以改动了一下默认构造方法中的类型变为可空,但是没有赋默认值,导致后续使用默认构造函数时,需要你传一个 parcel 进去,这时补上可空参数的默认值 = null 就可以了
No.2 Serializable 接口的 “传递” 问题
最近遇到一个问题,从某个页面返回手机系统 home 页面后,再打开 app 返回那个页面,会引发闪退,报错 java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = xxx.xxxx.xxxBean)。这是因为我们在某个 A 实体类中实现了 Serializable 接口,然后 A 类中有一些 B、C、D 其他类,这些 B、C、D 类却没有实现 Serializable 接口,而页面恢复时需要序列化来还原一些数据,这时进行序列化遇到没有实现 Serializable 接口的类就会报错,没有实现 Serializable 接口的类会在报错后具体写出,参考文章。因为父类声明了子类也需要声明,所以我把这个叫做 Serializable 接口的 “传递” 问题,经过一番检索,有下面三种处理方法
- 用 transient 来修饰类内不参与序列化/反序列化的属性。这个需要再仔细了解下 transient 修饰符,不能乱用,因为加上了这个,对应属性不参与序列化/反序列化,可能会影响页面数据的恢复
- 考虑一下属性的用途,看是否可以修改属性,不要直接用实体类,比如只需要一个 String 就能存储的信息,就不需要用一个类了。一般比较推荐这个,毕竟是做减法,复杂度更小了,毕竟你的 B、C、D 等类内可能还有 E、F、G 这些其他类,会越来越麻烦
- 用 Parcelable 来替代 Serializable。如果是简单的类还比较好弄,如果有很多字段,且这个类会比较频繁地加属性,那后面要一直维护这个类,不如 Seriallizable 简单。而且抽象类实现 Parcelable 接口貌似还比较复杂,不太好用
- 这三种处理方法的原文在这里,截图如下,贴出来供参考,综上所述,我比较推荐使用第 2 种方案,实在不行的话就要再考虑 1、3 这两种了
另外附上 《Android Studio 自动生成 SerialVersionUID》 文章供查阅
展开讲讲什么是 serialVersionUID?有什么用?
serialVersionUID 用来表明类的不同版本间的兼容性,其目的是以序列化对象进行版本控制,有关各版本反序加化时是否兼容
如果类没有显示定义这个静态变量,它的值是 JRE 根据类的内部细节自动生成的。若类做了修改,serialVersionUID 可能发生变化,故建议显式声明