Android中Serializable和Parcelable接口
16lz
2021-01-25
知人者智,自知者明。胜人者有力,自胜者强。——老子
最近在总结Activity之间数据传递的类型,我们都知道当Android中需要传递对象时一般要实现Serializable或Parcelable接口,但是只会写,对其一些内在的原理一点也不了解,阅读了多篇博客并亲自验证后,决定对Serializable和Parcelable的原理和使用做一个总结,如有谬误欢迎指正,如有疑问欢迎留言。我将在第一时间回答或改正。
一、Serializable意思是序列化,什么是序列化与反序列化? 对象的序列化:把对象转换为字节序列的过程称为对象的序列化。 反序列化:把字节序列恢复为Java对象的过程。 要想搞清楚序列化我们必须要清楚三点:Java对象、字节序列、存储。 ①Java对象 Java对象包含变量与方法。但是序列与反序列化仅处理Java变量而不处理方法,序列与反序列化仅对数据进行处理。 ②字节序列
其实就是连续排列的多个字符的序列,例如:“asdsdsfsdfsdff” ③存储 字符序列需要保存到一个地方,可以是硬盘也可以是内存。
简单说法是:序列化把当前对象信息保存下来。反序列化刚好相反的操作。 二、为什么要使用序列化? 在了解什么是序列化后可能会有人问为什么要使用序列化?它有什么用处? 从序列化的定义中我们可以看到它把一个对象转换成了流,并且将其保存到本地,那么我们就可以知道序列化主要有以下用途 (1)永久性保存对象,保存对象的字节序列到本地文件中; (2)通过序列化对象在网络中传递对象; (3)通过序列化在进程间传递对象(如:android通过序列化传递对象)。 三、Java对象与Java对象序列化的区别? Java对象存在的前提必须在JVM运行期间存在,如果想在JVM非运行的情况下或者在其他机器JVM上获取指定Java对象,在现有Java对象的机制下都不可能完成。
与Java对象不同的是,如果对Java对象执行序列化操作,因为原理是把Java对象信息保存到存储媒介,所以可以在以上Java对象不可能存在的两种情况下依然可以使用Java对象。 四、如何实现序列化 Android中实现序列化有两个选择:一是实现Serializable接口(是JavaSE本身就支持的),一是实现Parcelable接口(是Android特有功能,效率比实现Serializable接口高效,可用于Intent数据传递,也可以用于进程间通信(IPC))。实现Serializable接口非常简单,声明一下就可以了,而实现Parcelable接口稍微复杂一些,但效率更高,推荐用这种方法提高性能。
注:Android中Intent传递对象有两种方法:一是Bundle.putSerializable(Key,Object),另一种是Bundle.putParcelable(Key,Object)。当然这些Object是有一定的条件的,前者是实现了Serializable接口,而后者是实现了Parcelable接口。 两种序列化方法的比较: ①Serializable, 简单易用,效率低 serializable的迷人之处在于你只需要对某个类以及它的属性实现Serializable 接口即可。Serializable 接口是一种标识接口(marker interface),这意味着无需实现方法,Java便会对这个对象进行高效的序列化操作。 这种方法的缺点是使用了反射,序列化的过程较慢。这种机制会在序列化的时候创建许多的临时对象,容易触发垃圾回收。 ②Parcelable, 速度至上,代码量阅读和维护不易 根据Google工程师的说法,这些代码将会运行地特别快。原因之一就是我们已经清楚地知道了序列化的过程,而不需要使用反射来推断。同时为了更快地进行序列化,对象的代码也需要高度优化。因此,很明显实现Parcelable并不容易。实现Parcelable接口需要写大量的模板代码,这使得对象代码变得难以阅读和维护。 关于 Parcelable比 Serializable运行快慢的比较详见此博客 http://greenrobot.me/devpost/android-parcelable-serializable/ Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。而Android的Parcelable的设计初衷是因为Serializable效率过慢,为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable是通过IBinder通信的消息的载体。从Parcelable设计的初衷中我们也能够看到Parcelable的速度是比较快的那么我们如何选择使用哪种序列化方式呢?
如果你想成为一个优秀的软件工程师,你需要多花点时间来实现Parcelable,因为这将会为你对象的序列化过程快10多倍,而且占用较少的资源。 五、Parcelable接口定义
public interface Parcelable { //内容描述接口,基本不用管 public int describeContents(); //写入接口函数,打包 public void writeToParcel(Parcel dest, int flags); //读取接口,目的是要从Parcel中构造一个实现了 Parcelable的类的实例处理。因为实现类在这里还是不可知的,所以需要用到模板的方式,继承类名通过模板参数<span style="white-space:pre"></span> 传入<span style="white-space:pre"></span> //为了能够实现模板参数的传入,这里定义Creator嵌入接口,内含两个接口函数分别返回单个和多个继承类实例 public interface Creator<T> { public T createFromParcel(Parcel source); public T[] newArray( int size); } }六、应用举例
①实现Parcelable
实现Parcelable大致可以分为四个步骤:
1)implements Parcelable
2)重写writeToParcel方法,将你的对象序列化为一个Parcel对象,即:将类的数据写入外部提供的Parcel中,打包需要传递的数 据到Parcel容器保存,以便从 Parcel容器获取数据
3)重写describeContents方法,内容接口描述,默认返回0就可以
4)实例化静态内部对象CREATOR实现接口Parcelable.Creator
public static final Parcelable.Creator<T> CREATOR注: 其中public static final一个都不能少,内部对象CREATOR的名称也不能改变,必须全部大写 。需重写本接口中的两个方法:createFromParcel(Parcel in) 实现从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层,newArray(int size) 创建一个类型为T,长度为size的数组,仅一句话即可(return new T[size]),供外部类反序列化本类数组使用。
从Parcelable的实现步骤我们可以看到在此过程中: 通过writeToParcel将对象映射到Parceld对象,然后再通过createFromParcel将Parcel对象映射成你的对象。也可以将Parcel看成是一个流,通过writeToParcel把对象写到流里面,在通过createFromParcel从流里读取对象,只不过这个过程需要我们来实现, 因此写的顺序和读的顺序必须一 致 。
创建一个实现了Parcelable接口的类 Book类
package com.example.progressbar;import android.os.Parcel;import android.os.Parcelable;public class Book implements Parcelable { private String name; private int price;private String author; public Book() {} public Book(String name, int price, String author) { this.name = name; this.price = price; this.author = author;} public String getName() { return name; } public void setName(String name) { this.name = name;} public int getPrice() { return price;}public void setPrice(int price) { this.price = price;}public String getAuthor() { return author;} public void setAuthor(String author) { this.author = author;} @Overridepublic int describeContents() { return 0;}// 该方法将类的数据写入外部提供的Parcel中。@Overridepublic void writeToParcel(Parcel parcel, int i) { parcel.writeString(this.name); parcel.writeInt(this.price); parcel.writeString(this.author);} public static final Parcelable.Creator<Book> CREATOR = new Creator<Book>() {// 返回一个Book[i]供外部类反序列化本类数组使用 @Overridepublic Book[] newArray(int i) { return new Book[i];} @Override public Book createFromParcel(Parcel parcel) {// 将Parcel对象反序列化为Book对象return new Book(parcel.readString(),parcel.readInt(),parcel.readString()); } };}创建Student类实现Serializable,实现Serializable比较简单只需要implements Serializable 即可。这只是给对象打了一个标记,系统会自动将其序列化。 Student类
packagecom.example.progressbar;import java.io.Serializable;publicclassStudent implements Serializable { private static final long serialVersionUID = 1L;private String name; private int age;private String sex; public Student(){} public Student(String name,int age,String sex){ this.name=name; this.age=age; this.sex=sex;} public String getName() { return name;} public void setName(String name) { this.name = name;} public int getAge() { return age;} public void setAge(int age) { this.age = age;} public String getSex() { return sex;} public void setSex(String sex) { this.sex = sex; }}好了,这一篇博客就到这里了,看完了就留个言顶一个呗,您的支持是我前进的动力。
更多相关文章
- android添加wifi热点管理黑白名单
- Android(安卓)Training - 代码性能优化小技巧
- java/android 设计模式学习笔记(12)---组合模式
- AndroidCameraHAL3-MultiCamera-CameraX
- Service与Android系统设计(2)-- Parcel
- Activity任务栈和启动模式
- Android可绘制对象资源之shape和layer-list使用
- Android(安卓)SAX方式解析XML文件
- android直播中的一些流媒体技术浅析