文章目录

  • 关于序列化
  • Serializable
    • 简述原理
    • 怎么使用
  • Parcelable
    • Parcelable的实现原理
    • “包装公司”Parcel
      • 装包
      • 拆包
      • 小结
    • Parcelable的使用
  • 两者的区别
    • Serializable
    • Parcelable
  • 总结

关于序列化

这篇文章主要来讲一下在安卓中关于序列化的问题。首先了解一个问题:什么是序列化?为什么要用到序列化?

  • 什么是序列化:序列化就是就是把一个对象变成可传输的二进制流,可以进行传输。
  • 什么是反序列化:与序列化对应,反序列化就是把一个二进制流转化成对象。
  • 哪里用到序列化:上面说到序列化就是把对象变得可传输;例如在内存,或者网络中传输数据的时候,就得把一个对象变成二进制流可以进行传输。除此之外,在各种通信中,例如进程间通信,文件读取写入等等都要用到序列化。涉及到数据传输,就得使用序列化。因为只有二进制流才可以进行传输。
  • 我们在那些地方会遇到序列化:我们会发现,仅有基本数据类型可以自动进行序列化,但是我的自定义对象并不可以进行序列化。在哪里可以体现呢?当我们从一个Activity向另外一个Activity传递数据的时候,通过Intent,我们会发现只能放基本数据类型。
  • 怎么让自定义的对象可序列化:就是我们要讲的Serializable和Parcelable接口。这两个接口就可以让我们的自定义对象可序列化。

那这两个接口怎么使用?他们有什么区别?这就是接下来我要讲的。

Serializable

简述原理

Serializable只要使用Java的ObjectOutputStream与ObjectInputStream来开启流。而这个接口主要就是用来标识这个对象可以被转换。关于IO流的相关知识,读者有兴趣可以去深入了解,这里不做深入探究。

怎么使用

这个序列化接口是Java提供的,实现了这个接口的类,其实例就可以进行传输。那么这个接口怎么使用呢?
直接实现这个接口就行了。
因为这是一个空接口,所以使用方法极其简单,只需要实现这个接口即可。接下来看个例子:

public class Test implements Serializable {private String string1;private String string2;private int num;private Son son;private List<Son> list = new ArrayList<>();public String getString1() {return string1;}public void setString1(String string1) {this.string1 = string1;}public String getString2() {return string2;}public void setString2(String string2) {this.string2 = string2;}public int getNum() {return num;}public void setNum(int num) {this.num = num;}public Son getSon() {return son;}public void setSon(Son son) {this.son = son;}public List<Son> getList() {return list;}public void setList(List<Son> list) {this.list = list;}
}

这样就可以把这个Test对象序列化了。

Parcelable

同样是使对象可序列化,同样是继承接口,但是Parcelable相比Serializable就要复杂得多了。Paecelable需要在要序列化的类中利用Parcel重写序列化和反序列化的方法。

Parcelable的实现原理

Parcelable的实现原理主要就是在内存中开辟一个共享内存块,然后进行传输,看图:

如图在AB两个进程中要进行传输,不能直接把一个对象传输过去,开辟一块内存,通过Parcel,也就是打包的方式,把数据存在了共享内存,再把共享内存中的数据用Parcel取出来,实现数据传输。通俗点来讲,就像送外卖一样,商家找了外卖这个中间人,把食物打包给了外卖小哥,然后你再找外卖小哥拿外卖,再拆包就可以拿到食物了。
通过原理可以看到,实现这个接口的重点就在:装包,拆包。如果将对象里面的数据,一个个装起来,是我们要在类中实现的方法。而装拆包公司就是Parcel。所以首先来了解一下这个包装公司:Parcel!

“包装公司”Parcel

Parcel的使用和Intent是差不多的,就是write(put)进去,再read(get)出来。简单来看看怎么使用:

装包

直接上代码,相关方法说明看注释:

     Parcel parcel;//打包字符串parcel.writeString(String string);//打包整型数parcel.writeInt(int num);//打包布尔变量,要和bite进行转换parcel.writeByte((byte) (boolean bl? 1 : 0));//打包字符串集合parcel.writeStringList(List<String> list);//ElemType表示一个自定义类//序列化对象的时候传入要序列化的对象和一个flag,这里的flag的意思是是否要将这个作为返回值返回//一般传入0,要作为返回值就写1。另外这个对象也一定要是可序列化的parcel.writeParcelable(ElemType elem, 0);//这里写入自定义元素集合有两种方法,区别是是否写入类的信息//第一种方法是不写入类信息,相对应的取出来的时候要用Parcel把元素里面的每一个元素拿出来parcel.writeTypedList(mFriends);//第二种方法是写入类的信息,取出来的时候就要用类加载器去加载parcel.writeList(mFriends);//同样也要保证集合的元素可序列化

这里可以看到整体和Intent的传入数据是十分像的。重点有三个地方不太一样:

  • 布尔变量。布尔变量不能直接放进去,要转换成bite
  • 可序列化对象。这个放进去的时候要保证这个对象是可序列化的,也就是必须实现序列化接口
  • 集合。集合分为两种。一种是把元素类的信息也放进去,一种是不把元素的类的信息放进去。下面将拆包会详细讲一下。
拆包

直接上代码:(变量使用装包中的变量)

Parcel source;//这个对象在反序列化的时候会作为参数传入供给使用//获取字符串String string= source.readString();//获取整型int i = source.readInt();//获取布尔数boolean b = source.readByte() != 0;//这里注意转化//获取自定义对象// 读取对象需要提供一个类加载器去读取,因为写入的时候写入了类的相关信息ElemType e = source.readParcelable(ElemType.class.getClassLoader()); //获取字符串集合List<String> list = source.createStringArrayList();//这一类需要用相应的类加载器去获取//ElemType表示一个自定义类source.readList(List<Elemtype> list, ElemType.class.getClassLoader());//这一类需要使用自定义类的CREATOR,也就是使用Pacel的反序列方法去获取//source.readTypedList(ElemType e, ElemType.CREATOR); //对应writeTypeList//books = in.createTypedArrayList(ElemType.CREATOR); //对应writeTypeList

主要就是对于布尔变量以及集合的转换会比较不一样。
代码中的Friend.CREATOR是Parcelable接口中反序列的方法,实现原理也是用Parcel把对象里面的数据一个个转换出来。

  • 布尔变量要进行转换
  • 对象要用类加载器去加载。因为写入的时候写入了类信息
  • 集合看情况;写入了类信息就要用类加载器;否则用反序列的方法。
小结

Parcel的使用方法和Intent很像,但是有几个点要注意一下:

  • Parcel中没有布尔变量,所以必须将布尔变量和bite进行转换
  • Parcel包装自定义对象时,这个对象对应的类必须也得是实现了序列化接口的才可以进行打包。装包的这个方法因为写入了类的信息,所以拆包的时候需要用到对应类的加载器来进行加载。
  • Parcel在包装集合的时候有两种方法:一种是写入类的信息,一种是不写入类的信息。但都有一个前提:集合中的元素必须是可序列化的。第一种方法需要用到类加载器去加载,第二种就需要用到自定义类中的Parcel的反序列化方法。
  • 对于类中有多个相同类型的数据,例如3个字符串,3个int等等,存入的顺序和取出来的顺序一定要一致。例如存int a,int b;那么取出来的时候也得是int a,int b。不能颠倒。

Parcelable的使用

看完了上面的Pacel可能还是有一点懵,那这个怎么Parcelable怎么用Pacel实现呢?Parcelable的主要实现思路就是把一个对象中的数据进行分解,分解出来的数据都是可以用Parcel打包的。Parcelable具体怎么使用呢?接下来就来看一下。先看看谷歌给出的示例(代码很重要,记得看注释):

//首先要实现Parcelable接口
public class MyParcelable implements Parcelable {//类中的数据private int mData;//接下来这两个方法是关于序列化的。一定要重写的两个方法//第一个方法是内容描述。一般没什么要求都是返回0就行了public int describeContents() {return 0;}//第二个是序列化数据的方法。当我们序列化这个类的对象的时候就会调用到这个方法//两个参数:一个是Pacel“包装公司”上面我们讲的,一个是flags。第二个参数表示是否把数据返回。一般为0.//利用这个Parcel把类中所有的数据“打包”序列化public void writeToParcel(Parcel out, int flags) {//这个就是上面我们介绍的Parcel的使用out.writeInt(mData);}//接下来的这两个就是关于反序列化的了//CREATOR是Parcelable中的一个静态变量,这个名字不能改,因为他内部调用的时候就是用CREATOR来调用的改了名字就找不到了//观察我们上面的Pacel使用方法也可以发现,是传入ElemType.CREATOR。如果改了名字就找不到了。//Creator对象中有两个方法要重写:public static final Creator<MyParceable> CREATOR= new Creator<MyParceable>() {//这个就是反序列方法了。在Pacel中把数据取出来构建成一个MyParcelable对象public MyParcelable createFromParcel(Parcel in) {//这里我们用到构造器来获取这个对象。具体构造器实现方法在下面return new MyParcelable(in);}//这个是开辟数组供给使用。一般按照下面的格式写就好了。public MyParcelable[] newArray(int size) {return new MyParcelable[size];}};//这个是构造器。从Parcel中把数据取出来  private MyParcelable(Parcel in) {//这里就用到了上面我们讲的Parcel的获取数据的方法了mData = in.readInt();}

通过上面的代码相信也可以很清晰的了解怎么实现了。主要就是分为两个部分:序列化和反序列化。

  • 序列化主要就是用一个Parcel把数据封装起来。怎么使用按照上面的Parcel使用方法。
  • 反序列化要用到一个静态变量,这也可以说是一个构造器,Creator本身就是创造的意思嘛。通过这个Creator吧Parcel中的数据取出来再构造成一个对象,对应拆包。具体我们使用构造器来实现。构造器里面用Parcel的获取数据方法来把数据取出来。需要注意的是这里的CREATOR名字不能改。

两者的区别

好了。到这里相信都了解怎么使用这两个接口了。主要是Parcelable比较复杂。现在有个问题了,为什么要造一个如此复杂的接口呢?来看看他们各自的优缺点。

Serializable

这个是java内部定义的序列化接口。

  • 优点:使用范围广,在网络,内存文件等均可以使用;使用方式简单,仅仅只需要继承一个接口就可以使用。
  • 缺点:性能差;序列化的时候需要创建很多的临时对象。
Parcelable

这个安卓中可以使用的接口,仅用于安卓。

  • 优点:性能强大。开发者号称比Serialization强大10倍的性能。
  • 缺点:实现过程复杂,需要把对象中的数据一个个拆开进行序列化;
    从实现原理可以看出来,这个只能用于内存中的序列化,不能用于网络和本地硬盘文件。

总结

序列化在安卓开发中还是很常用的,例如活动之间传递信息,跨进程传递数据等等都要用到。这两个接口一个简单粗暴,一个复杂强大,平常开发的话,尽量还是使用第二个接口,毕竟多一点代码可以加强这么多的性能何乐不为呢。Parcelable可能比较难理解,多看几遍就可以了。不理解或者笔者写错的可以评论区留言。

简析Java中的Serializable与Android中的Parcelable序列化相关推荐

  1. android 序列化 xml serializable,关于Android中的序列化Serializable和Parcelable的学习

    简单地说,"序列化"就是将运行时的对象状态转换成二进制,然后保存到流,内存或者通过网络传输给其他端. 两者最大的区别在于 存储媒介的不同,Serializable使用 I/O 读写 ...

  2. android Java开发设计模式及在android中的应用解析

    android Java开发设计模式及在android中的应用解析 什么是设计模式: 可以用一句话概括设计模式---设计模式是一种利用OOP的封闭.继承和多态三大特性,同时在遵循单一职责原则.开闭原则 ...

  3. java除了android,Java中是否有类似android中的android.os.Handler的类?

    没有一个默认.但是你可以让自己的自定义类来做类似的事情. 我做了一个这样的: import java.util.ArrayList; public class Handler extends Obje ...

  4. Java中beimage_GitHub - beconf/ImageBlurring: Android 中通过 Java 与 JNI 分别进行图片模糊;并且进行比较其运算速度。...

    ImageBlurring Android 中通过 Java 与 JNI 分别进行图片模糊:并且进行比较其运算速度. 相关文章 备注消息 Screenshots RenderScript Fast B ...

  5. Java泛型应用之打造Android中ListView和GridView万能适配器【CommonAdapter】--超简洁写法

    转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/52813227 [DylanAndroid的csdn博客] 在android中使 ...

  6. 简析 Java语言的过载与重载

    复习一下 :  过载 (override)     重载 (overload)  在代码实践中 理清概念. package sub;/*** 简析 过载与重载* User: yiminghe* Dat ...

  7. android androidruntime java,java – Runtime.exec():在Android中重启?

    重新启动在Android中正常工作.你可能没有正确地执行runtime.exec(). 你需要处理 public static void rebootSU() { Runtime runtime = ...

  8. 【译】Android中的安全数据— Android中的加密(第2部分)

    目录 锁屏 选择一个钥匙 密钥存储 密钥生成 密钥管理 加密与解密 使用范例 下一步是什么 安全提示 锁屏 如果要保护数据,请保护设备. 为了更加安全,在提供对任何应用程序功能的访问权限之前,我们可以 ...

  9. 【译】Android中的安全数据— Android中的加密(第1部分)

    目录 Java密码体系结构 Android Key Store 样例项目 下一步是什么 安全提示 Java密码体系结构 Android建立在Java密码体系结构(JCA)的基础上,该体系结构提供了用于 ...

最新文章

  1. cto denalil
  2. Oculus和虚拟现实的无限可能
  3. 《Go语言圣经》学习笔记 第三章 基础数据类型
  4. oracle 多路径 SAN,前言 - Oracle Solaris 管理:SAN 配置和多路径
  5. java day12【Object类、常用API】
  6. 一道错误答案传遍全网的逻辑面试题
  7. javaweb不同用户登录不同页面的页面_ssh+mysql实现的Java web论坛系统源码附带视频指导运行教程...
  8. 数据结构 复习攻略 新手必看
  9. JAVA判断素数法+引用方法
  10. 《Revisiting Pre-trained Models for Chinese Natural Language Processing》(MacBERT)阅读记录
  11. 手机背景图片被删除怎么恢复
  12. Java将英文句子分解为单词
  13. PIA (Primary Interop Assembly) AIA (Alternate Interop Assembly)简介
  14. 第四章 大数定律与中心极限定理(总结)
  15. Linux tar/rpm/yum命令软件安装
  16. 开源PLM软件Aras详解六 角色与用户以及权限
  17. iOS app集成使用 Facebook 深度链接
  18. ABBYY FineReader 14扫描和保存文档
  19. illustrator下载_如何在Illustrator中创建光泽的圣诞摆设
  20. 通通通2006+浩方打星际问题

热门文章

  1. 二嗨租车系统java_Java第二季-嗒嗒租车系统
  2. 基于osgEarth搭建三维可视化平台 第3讲 加载高程数据
  3. sheng的学习笔记-synchronized底层实现原理
  4. 关于mysql如何创建多用户
  5. insmod加载分析
  6. QT中OpenGL开发起步
  7. 自学java 答答租车系统
  8. HAVE FUN | 源码解析活动最新进展
  9. AppCode2018.2安装(破解) Mac
  10. 【开源项目】基于神念TGAM的脑波灯