序列化

- 序列化是什么?⭐⭐⭐⭐
- 序列化的作用?什么时候需要序列化? ⭐⭐⭐⭐
- Android中序列化方式有几种?说说它们的区别。⭐⭐⭐⭐⭐
- Bunder传递对象为什么需要序列化?⭐⭐⭐
序列化是什么?序列化的作用?什么时候需要序列化?
字节流便于存储且便于传输,序列化的作用有:
- 进行网络传输:将对象或者信息数据转换为字节流格式,特别是Base64格式,并通过网络传输给其他人;
- 本地永久性存储:将对象转换为字节流并存放于内存,等到需要用到该对象的时候,再从内存读取字节流并再次构建出该对象;
- 进行IPC传输:如需要将某个对象的信息传输给其他的进程,则需要先进行序列化,传输到其他进程后,再将其反序列化构建出原来的对象; 那么,针对将对象转换为字节流的过程称之为“序列化”,而将字节流再次构建为对象的则是“反序列化”。
如何实现序列化
在Android中有两种实现序列化的方式:
Serializable
这是Java自带的序列化方法,可以通过实现Serializable接口来实现序列化。序列化后的对象可以进行网络传输,也可以存储到本地磁盘。然而这个方式并不推荐,因为其内部实现原理是通过Java的反射机制 ,该机制效率相对低,同时会产生很多临时对象,因此就需要频繁地进行垃圾回收;
1 | //构建一个实现了Serializable接口的类 |
上面注释1就是将entity变量进行序列化,转换为字节流后存放在Bundle里(Bundle主要用于传递数据,它保存的数据,是以key-value(键值对)的形式存在的)。在注释2,再次通过反序列化构建出原来的对象。
Parcelable
使用方法
这是安卓专用的序列化方式。Parcelable接口比Serializable接口效率更高,性能方面要高出10多倍。因为其实现原理是把对象分解为Intent支持的数据类型,并通过Intent进行传输,其数据可以保存在内存中,相对于Serializable将数据保存在磁盘,效率自然更高。Parcelable的用法如下:
1 | // CutInfo.java 定义一个CutInfo类 |
Parcelable解析
了解Parcelable就要先了解什么是Parcel,即[注释3]
的Parcel。Parcel翻译过来就是“打包”的意思。通过Parcel可以讲序列化后的数据写入一片共享内存中,其他进程再通过Parcel从共享内存读取数据,并反序列化得到目标对象。
接着,一个类要实现Parcelable接口,需要实现以下两个接口:
- describeContents:负责文件描述,只针对一些特殊的需要描述信息的对象,需要返回1,其他情况返回0即可,对应
[注释4]
。 - writeToParcel:通过writeToParcel方法实现序列化。
反序列化需要定义一个CREATOR的变量,通过匿名内部类实现Parcelable中的Creator的接口。对应[注释5]
。
Bunder传递对象为什么需要序列化?
因为bundle传递数据时只支持基本数据类型,所以在传递对象时,需要先将对象进行序列化,转换成可存储或可传输的字节流。
Android为什么引入Parcelable?Serialzable和Parcelable的区别?
- Serialzable序列后的数据存在磁盘上,Parcelable则是直接在内存中读写,因此效率更高;
- Serialzable是Java自带的序列化方法,使用Java的反射机制,效率相对低,且会产生大量临时对象,导致频繁进行垃圾回收;Parcelable 是自己实现封送和解封,通过将对象分解为Intent所支持的数据类型进行传输。
- Parcelable相比较Serializable要复杂的很多,Serializable序列化只要对象继承该接口,即可。但是Parcelable则需要实现writeToParcel、describeContents函数以及静态的CREATOR变量,实际上就是将如何打包和解包的工作自己来定义,而序列化的这些操作完全由底层实现。