Android中的序列化机制

编程入门 行业动态 更新时间:2024-10-25 14:26:06

Android中的序列化<a href=https://www.elefans.com/category/jswz/34/1771042.html style=机制"/>

Android中的序列化机制

文章写于以前,部分内容出处不记得了,如有侵权请联系删除或注明出处。
Android中有两种序列化机制一个是java本身的Serializable一个是android的Parcelable
Serializable 数据持久化 实现简单 消耗大(性能内存)

Parcelable主要用于内存间数据传输

1、Serializable 直接继承

intent.putExtra("person",new Person("Lucy",30));
Person person = (Person)intent.getSerializableExtra("person");

2、Parcel的简介

​ 简单来说,Parcel提供了一套机制,可以将序列化之后的数据写入到一个共享内存中,其他进程通过Parcel可以从这块共享内存中读出字节流,并反序列化成对象,下图是这个过程的模型。

Parcel可以包含原始数据类型(用各种对应的方法写入,比如writeInt(),writeFloat()等),可以包含Parcelable对象,它还包含了一个活动的IBinder对象的引用,这个引用导致另一端接收到一个指向这个IBinder的代理IBinder。
Parcelable通过Parcel实现了read和write的方法,从而实现序列化和反序列化

实现Parcelable的作用

1)永久性保存对象,保存对象的字节序列到本地文件中;

2)通过序列化对象在网络中传递对象;

3)通过序列化在进程间传递对象。

首先写一个类实现Parcelable接口,会让我们实现两个方法:

  • describeContents 描述
    其中describeContents就是负责文件描述.通过源码的描述可以看出,只针对一些特殊的需要描述信息的对象,需要返回1,其他情况返回0就可以

  • writeToParcel 序列化
    我们通过writeToParcel方法实现序列化,writeToParcel返回了Parcel,所以我们可以直接调用Parcel中的write方法,基本的write方法都有,对象和集合比较特殊下面单独讲,基本的数据类型除了boolean其他都有,Boolean可以使用int或byte存储

我们将上面的Album对象实现序列化,Album对象包含四个字段。

反序列化

反序列化需要定义一个CREATOR的变量,上面也说了具体的做法,这里可以直接复制Android给的例子中的,也可以自己定义一个(名字千万不能改),通过匿名内部类实现Parcelable中的Creator的接口

Parcelable中对象和集合的处理

import android.os.Parcel;
import android.os.Parcelable;import java.util.ArrayList;/*** Created by fengxing on 2018/3/28.*/public class ParcelDemo implements Parcelable {private int count;private String name;private ArrayList<String> tags;private Book book;// ***** 注意: 这里如果是集合 ,一定要初始化 *****private ArrayList<Book> books = new ArrayList<>();/*** 序列化** @param in*/protected ParcelDemo(Parcel in) {count = in.readInt();name = in.readString();tags = in.createStringArrayList();// 读取对象需要提供一个类加载器去读取,因为写入的时候写入了类的相关信息book = in.readParcelable(Book.class.getClassLoader());//读取集合也分为两类,对应写入的两类//这一类需要用相应的类加载器去获取in.readList(books, Book.class.getClassLoader());// 对应writeList//这一类需要使用类的CREATOR去获取in.readTypedList(books, Book.CREATOR); //对应writeTypeList//books = in.createTypedArrayList(Book.CREATOR); //对应writeTypeList//这里获取类加载器主要有几种方式getClass().getClassLoader();Thread.currentThread().getContextClassLoader();Book.class.getClassLoader();}public static final Creator<ParcelDemo> CREATOR = new Creator<ParcelDemo>() {@Overridepublic ParcelDemo createFromParcel(Parcel in) {return new ParcelDemo(in);}@Overridepublic ParcelDemo[] newArray(int size) {return new ParcelDemo[size];}};/*** 描述** @return*/@Overridepublic int describeContents() {return 0;}/*** 反序列化** @param dest* @param flags*/@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeInt(count);dest.writeString(name);//序列化一个String的集合dest.writeStringList(tags);// 序列化对象的时候传入要序列化的对象和一个flag,// 这里的flag几乎都是0,除非标识当前对象需要作为返回值返回,不能立即释放资源dest.writeParcelable(book, 0);// 序列化一个对象的集合有两种方式,以下两种方式都可以//这些方法们把类的信息和数据都写入Parcel,以使将来能使用合适的类装载器重新构造类的实例.所以效率不高dest.writeList(books);//这些方法不会写入类的信息,取而代之的是:读取时必须能知道数据属于哪个类并传入正确的Parcelable.Creator来创建对象// 而不是直接构造新对象。(更加高效的读写单个Parcelable对象的方法是:// 直接调用Parcelable.writeToParcel()和Parcelable.Creator.createFromParcel())dest.writeTypedList(books);}
}

Book类,需要先实现Parcelable,实现步骤就不贴出来了,和普通的对象一样,实现三个过程。

import android.os.Parcel;
import android.os.Parcelable;/*** Created by fengxing on 2018/3/28.*/public class Book implements Parcelable {protected Book(Parcel in) {}public static final Creator<Book> CREATOR = new Creator<Book>() {@Overridepublic Book createFromParcel(Parcel in) {return new Book(in);}@Overridepublic Book[] newArray(int size) {return new Book[size];}};@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {}
}

写入和读取集合有两种方式,
一种是写入类的相关信息,然后通过类加载器去读取, –> writeList | readList
二是不用类相关信息,创建时传入相关类的CREATOR来创建 –> writeTypeList | readTypeList | createTypedArrayList
第二种效率高一些
一定要注意如果有集合定义的时候一定要初始化 like this –>
public ArrayList<T> demo = new ArrayList<>();

举个详细的例子:

class MessageFilter() : Parcelable{var sender: List<FilterSender>? = nullvar messageType: FilterMessageType? = nullvar time: FilterTime? = null//读数据进行恢复constructor(parcel: Parcel) : this() {this.sender = mutableListOf()parcel.readList(sender, FilterSender.javaClass.classLoader)messageType = parcel.readParcelable(FilterMessageType.javaClass.classLoader)time = parcel.readParcelable(FilterTime.javaClass.classLoader)}//写数据进行保存override fun writeToParcel(dest: Parcel?, flags: Int) {dest?.writeList(sender)dest?.writeParcelable(messageType, Parcelable.PARCELABLE_WRITE_RETURN_VALUE)dest?.writeParcelable(time, Parcelable.PARCELABLE_WRITE_RETURN_VALUE)}override fun describeContents(): Int {return 0}companion object CREATOR : Parcelable.Creator<MessageFilter> {override fun createFromParcel(parcel: Parcel): MessageFilter {return MessageFilter(parcel)}override fun newArray(size: Int): Array<MessageFilter?> {return arrayOfNulls(size)}}
}//涉及到的相关类都需要实现Parcelable接口
data class FilterSender(val type: String, val id: String): Parcelable {constructor(parcel: Parcel) : this(parcel.readString(),parcel.readString())override fun writeToParcel(dest: Parcel?, flags: Int) {dest?.writeString(type)dest?.writeString(id)}override fun describeContents(): Int {return 0}companion object CREATOR : Parcelable.Creator<FilterSender> {override fun createFromParcel(parcel: Parcel): FilterSender {return FilterSender(parcel)}override fun newArray(size: Int): Array<FilterSender?> {return arrayOfNulls(size)}}
}

区别

Parcelable和Serializable的区别和比较

Parcelable和Serializable都是实现序列化并且都可以用于Intent间传递数据,Serializable是Java的实现方式,可能会频繁的IO操作,所以消耗比较大,但是实现方式简单 Parcelable是Android提供的方式,效率比较高,但是实现起来复杂一些 , 二者的选取规则是:内存序列化上选择Parcelable, 存储到设备或者网络传输上选择Serializable(当然Parcelable也可以但是稍显复杂)

选择序列化方法的原则

1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。

2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。

3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。

延伸:

下面介绍下ParcelableSerializable的作用、效率、区别及选择。

1、作用

Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。而Android的Parcelable的设计初衷是因为Serializable效率过慢,为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable是通过IBinder通信的消息的载体。

从上面的设计上我们就可以看出优劣了。

2、效率及选择

Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如activity间传输数据,而Serializable可将数据持久化方便保存,所以在需要保存或网络传输数据时选择Serializable,因为android不同版本Parcelable可能不同,所以不推荐使用Parcelable进行数据持久化。

3、编程实现

对于Serializable,类只需要实现Serializable接口,并提供一个序列化版本id(serialVersionUID)即可。Parcelable则需要实现writeToParceldescribeContents函数以及静态的CREATOR变量,实际上就是将如何打包和解包的工作自己来定义,而序列化的这些操作完全由底层实现。

4、高级功能上

Serializable序列化不保存静态变量,可以使用Transient关键字对部分字段不进行序列化,也可以覆盖writeObjectreadObject方法以实现序列化过程自定义。

更多推荐

Android中的序列化机制

本文发布于:2024-02-06 04:57:46,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1746593.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:机制   序列化   Android

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!