为了账号安全,请及时绑定邮箱和手机立即绑定

【九月打卡】第3天 Android 中的序列化 Serializable 和 Parcelable

标签:
Android

课程名称BAT大牛亲授技能+技巧 Android面试快速充电升级
课程章节:Android基础相关面试问题
主讲老师DocMike

课程内容

1. 序列化和反序列化

序列化是将对象的状态信息转化为可以存储或者传输形式的过程。比如将内存中的对象转化成可以保存在磁盘中的对象就是序列化的过程;反之,将磁盘或其它介质中的对象转化成内存中的对象的过程就是反序列化的过程。

Java 中创建的对象,并且只要对象没有被回收我们都可以复用此对象。但是,我们创建出来的这些对象都存在于 JVM 中的堆中,只有 JVM 处于运行状态的时候,这些对象才可能存在。一旦 JVM 停止,这些对象也就随之消失,但是在实际过程中,可能需要将这些对象持久化下来,并且在需要的时候将对象重新读取出来,Java 序列化可以帮助我们实现该功能。

2. Serializable 序列化

Java 类通过实现 Serializable 接口来启用序列化功能,未实现此接口的类将无法将其任何状态或者信息进行序列化或者反序列化。可序列化类的所有子类型都是可以序列化的。序列化接口没有方法或者字段,仅用于标识可序列化的语义。

Serializable 序列化方式比较简单,只需要将实体类实现 Serializable 接口即可,但是有一点需要注意,一般情况下最好设置一下 serialVersionUID,serialVersionUID 不是必须的,它会影响到反序列化的过程。序列化过程中,会把当前类的 serialVersionUID 写入文件当中,当进行反序列化时,会去检测当前类的 serialVersionUID 和写入文件的 serialVersionUID 进行比较,如果相同,表明当前类没有发生改变,可以反序列化成功;如果不相同,说明当前类发生过改变,例如成员变量改变,最终导致序列化失败。

如果不指定 serialVersionUID,系统会默认生成一个 serialVersionUID,这个 serialVersionUID 是根据当前类计算的 hash 值,如果类没有改变,这个 serialVersionUID 反序列化前后是一致;如果当前类发生过改变,例如成员变量改变,在检验 serialVersionUID 时,会重新计算当前类的 hash,这时候的 serialVersionUID 也跟着发生改变,和从文件中读取的 serialVersionUID 不再一致,导致反序列化失败。

3. Parcelable 序列化

在 Android 中,除了通过实现 Serializable 接口来实现序列化,还可以通过实现 Parcelable 接口,来进行序列化和反序列化,Parcelable 方式不同于将对象进行序列化,它的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了。通常 Parcelable 序列化作为 Intent 和 Binder 的数据传递。

使用 Parcelable 序列化,代码写起来会有点麻烦,不过好在 AndroidStudio 中只要设置好字段,自动实现接口时,会帮我们自动填充需要实现的代码,实现 Parcelable 的步骤:

  1. 重写 writeToParcel() 方法,对象序列化为一个 Parcel 对象,即将类的数据写入外部提供的 Parcel 中,打包需要传递的数据到 Parcel 容器保存,以便从 Parcel 容器获取数据;

  2. 重写 describeContents() 方法,内容接口描述,默认返回 0 就可以;

  3. 实例化静态内部对象 CREATOR 实现接口 Parcelable.Creator。其中 public static final 一个都不能少,内部对象 CREATOR 名称也不能改变,必须全部大写。 需重写本接口中的两个方法:createFromParcel() 和 newArray()。 createFromParcel() 方法实现从 Parcel 容器中读取传递数据值,封装成 Parcelable 对象返回逻辑层,newArray() 方法创建一个类型为T,长度为size的数组,仅一句话即可(return new T[size]),供外部类反序列化本类数组使用。

通过 writeToParcel() 将对象映射成 Parcel 对象,再通过 createFromParcel() 将 Parcel 对象映射成对象。也可以将 Parcel 看成是一个流,通过 writeToParcel() 把对象写到流里面,在通过 createFromParcel() 从流里读取对象。

4. Serializable 和 Parcelable 差异

  1. 使用内存序列化时,Parcelable 比 Serializable 性能高,所以推荐使用 Parcelable。

  2. Serializable 在序列化的时候会产生大量的临时变量,容易引起频繁的 GC,同时需要大量的 IO 操作,效率没有 Parcelable 高。内存间传递数据推荐使用 Parcelable,Serializable 数据持久化方便,对象序列化存储设备中,推荐使用 Serializable,能解决因为 Android 版本的兼容问题,引起的序列化失败的问题。

  3. 需要在多个组件( Activity 或 Service)之间通过 Intent 传递一些数据,简单类型(如:数字、字符串)的可以直接放入 Intent,复杂类型必须实现 Parcelable 接口。

课程总结

这一节通过 Serializable 和 Parcelable 从性能、实现方式和适用场景的对比,加深了对序列化的理解,能过做到知其然,并知其所以然。在不同的场景,选择最合适的序列化方式。

图片描述
图片描述

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
移动开发工程师
手记
粉丝
12
获赞与收藏
17

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消