漫谈序列化—使用、原理、问题(下)

简介: 天天跟我说给我介绍对象对象,对象在哪里?哪里有对象?

原理


先说说Parcelable写法中这几个方法参数的意思:


  • createFromParcel,User(Parcel in) ,代表从序列化的对象中创建原始对象
  • newArray,代表创建指定长度的原始对象数组
  • writeToParcel,代表将当前对象写入到序列化结构中。
  • describeContents,代表返回当前对象的内容描述。如果还有文件描述符,返回1,否则返回0。


好了,在了解Parcelable原理之前,我们先要了解下Parcel


Parcel是一个容器,它主要用于存储序列化数据,然后可以通过Binder在进程间传递这些数据


所以Parcel就是可以进行IPC通信的容器,同样底层也是用到了Binder。(Binder在Android中真是无处不在啊)


//写入数据
Parcel parcle = Parcel.Obtain();
parcel.writeString(String val);
//读取数据
parcel.setDataPosition(i);
parcel.readString();


再往底层就是Binder的原理了,也就是将数据写到内核的共享内存中,然后其他进程可以从共享内存中进行读取。


2.png


Parcelable的实现就是基于这个Parcel容器,还记得刚才的几个方法吗:


  • writeToParcel,写入数据到Parcel容器。
  • new User(in),从Parcel容器读取数据。

Parcelable的原理就是如此啦。


思考问题


介绍完了两种序列化方式,我们再来看看文章开头的这些问题。


在java有Serializable的前提下,Android为什么设计出了Parcelable?


java中的序列化方式Serializable效率比较低,主要有以下原因:


  • Serializable在序列化过程中会创建大量的临时变量,这样就会造成大量的GC。
  • Serializable使用了大量反射,而反射操作耗时。
  • Serializable使用了大量的IO操作,也影响了耗时。


所以Android就像重新设计了IPC方式Binder一样,重新设计了一种序列化方式,结合Binder的方式,对上述三点进行了优化,一定程度上提高了序列化和反序列化的效率。


Serializable、Parcelable、Json等序列化方式我们该怎么选择?


先说说序列化的用处,主要用在三个方面:


1、内存数据传输


内存传输方面,主要用Parcelable。一是因为Parcelable在内存传输的效率比Serializable高。二是因为在Android中很多传输数据的方法中,自带了对于Serializable、Parcelable类型的传输方法。比如:


  • Bundle.putParcelable,
  • Intent putExtra(String name, Parcelable value)


等等吧,基本上对象传输的方法都支持了,所以这也是Parcelable的优势。


2、 数据持久化(本地存储)


如果只针对Serializable和Parcelable两种序列化方式,需要选择Serializable。


首先,Serializable本身就是存储到二进制文件,所以用于持久化比较方便。而Parcelable序列化是在内存中操作,如果进程关闭或者重启的时候,内存中的数据就会消失,那么Parcelable序列化用来持久化就有可能会失败,也就是数据不会连续完整。而且Parcelable还有一个问题是兼容性,每个Android版本可能内部实现都不一样,知识用于内存中也就是传递数据的话是不影响的,但是如果持久化可能就会有问题了,低版本的数据拿到高版本可能会出现兼容性问题。


但是实际情况,对于Android中的对象本地化存储,一般是以数据库、SP的方式进行保存。


3、 网络传输


而对于网络传输的情况,一般就是使用JSON了。主要有以下几点原因:


  • 1、轻量级,没有多余的数据。
  • 2、与语言无关,所以能兼容所有平台语言。
  • 3、易读性,易解析。


Parcelable一定比Serializable快吗?


正常情况下,对象在内存中进行传输确实是Parcelable比较快,但是Serializable是有缓存的概念的,有人做了一个比较有趣的实验:


当序列化一个超级大的对象图表(表示通过一个对象,拥有通过某路径能访问到其他很多的对象),并且每个对象有10个以上属性时,并且Serializable实现了writeObject()以及readObject(),在平均每台安卓设备上,Serializable序列化速度大于Parcelable 3.6倍,反序列化速度大于1.6倍.


具体原因就是因为Serilazable的实现方式中,是有缓存的概念的,当一个对象被解析过后,将会缓存在HandleTable中,当下一次解析到同一种类型的对象后,便可以向二进制流中,写入对应的缓存索引即可。但是对于Parcel来说,没有这种概念,每一次的序列化都是独立的,每一个对象,都当作一种新的对象以及新的类型的方式来处理。


具体过程可以看看这篇:https://juejin.cn/post/6854573218334769166


为什么Java提供了Serializable的序列化方式,而不是直接使用json或者xml?


我觉得是历史遗留问题。


有的人可能会想到各种理由,比如可以标记哪些类可以被序列化。又或者可以通过UID来标示反序列化为同一个对象。等等。


但是我觉得最大的问题还是历史遗留问题,在以前,json还没有成为大家认同的数据结构,所以Java就设计出了Serializable的序列化方式来解决对象持久化和对象传输的问题。然后Java中各种API就会依赖于这种序列化方式,这么些年过去了,Java体系的庞大也造成难以改变这个问题,牵一发而动全身。


为什么我这么说呢?


主要有两点依据:



  • 二是因为在Serializable类的介绍注释中,明确说到推荐大家选择JSON 和 GSON库,因为它简洁、易读、高效。


* <h3>Recommended Alternatives</h3>
 * <strong>JSON</strong> is concise, human-readable and efficient. Android
 * includes both a {@link android.util.JsonReader streaming API} and a {@link
 * org.json.JSONObject tree API} to read and write JSON. Use a binding library
 * like <a href="http://code.google.com/p/google-gson/">GSON</a> to read and
 * write Java objects directly.


Android体系架构


连载文章、脑图、面试专题:


https://github.com/JiMuzz/Android-Architecture


参考


https://developer.android.google.cn/reference/android/os/Parcel?hl=enhttps://blog.csdn.net/lwj_zeal/article/details/90743500https://juejin.cn/post/6854573218334769166#headinghttp://blog.sina.com.cn/s/blog_6e07f1eb0100rsax.htmlhttps://www.zhihu.com/question/283510695https://www.infoworld.com/article/3275924/oracle-plans-to-dump-risky-java-serialization.html

目录
相关文章
|
3月前
|
Java
JDK序列化原理问题之Hessian框架不支持writeObject/readObject方法如何解决
JDK序列化原理问题之Hessian框架不支持writeObject/readObject方法如何解决
|
3月前
|
自然语言处理 JavaScript 前端开发
JDK序列化原理问题之FuryJDK序列化性能问题的如何解决
JDK序列化原理问题之FuryJDK序列化性能问题的如何解决
|
3月前
|
缓存 Java
JDK序列化原理问题之Fury如何实现与JDK序列化100%兼容的如何解决
JDK序列化原理问题之Fury如何实现与JDK序列化100%兼容的如何解决
|
3月前
|
Java
JDK序列化原理问题之在JDK序列化中不同JDK版本字段不一致的情况如何解决
JDK序列化原理问题之在JDK序列化中不同JDK版本字段不一致的情况如何解决
|
6月前
|
缓存 自然语言处理 JavaScript
万字长文深度解析JDK序列化原理及Fury高度兼容的极致性能实现
Fury是一个基于JIT动态编译的高性能多语言原生序列化框架,支持Java/Python/Golang/C++/JavaScript等语言,提供全自动的对象多语言/跨语言序列化能力,以及相比于别的框架最高20~200倍的性能。
168715 12
|
6月前
|
存储 XML JSON
日常小知识点之序列化结构(protobuf使用及简单原理)
日常小知识点之序列化结构(protobuf使用及简单原理)
180 0
|
6月前
|
存储 Java 开发工具
[Android]序列化原理Parcelable
[Android]序列化原理Parcelable
123 0
|
6月前
|
存储 Java Android开发
[Android]序列化原理Serializable
[Android]序列化原理Serializable
91 0
|
6月前
|
安全 Java
Java单例---序列化破坏单例模式原理解析(二)
Java单例---序列化破坏单例模式原理解析
51 0
|
6月前
|
Java
Java单例---序列化破坏单例模式原理解析(一)
Java单例---序列化破坏单例模式原理解析
77 0