Android序列化Serializable和Parcelable的理解和区别
2017-12-22 19:48
701 查看
一.基本概念
(一)序列化的基本概念
在Android开发过程中,因为无法将对象的引用传给Activities或者Fragments,我们需要将这些对象放到一个Intent或者Bundle里面,然后再传递。序列化,表示将一个对象转换成可存储或可传输的状态。而序列化后的对象,可以在网络上进行传输,也可以存储到本地。
(二)怎么通过序列化传输对象
Android中Intent如果要传递类对象,可以通过两种方式实现。1.方式一:Serializable,要传递的类实现Serializable接口传递对象
2.方式二 : Parcelable,要传递的类实现Parcelable接口传递对象。
Serializable(Java自带):
Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。
Parcelable(Android 专用):
除了Serializable之外,使用Parcelable也可以实现相同的效果,
不过不同于将对象进行序列化,Parcelable方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了。
二.基本使用
(一)Serializable, 简单易用
我们先看Serializable的代码。弄一个实体类 Person,利用Java自带的Serializable进行序列化public class Person implements Serializable{ private static final long serialVersionUID = 7382351359868556980L; private String name; private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
在数据传递界面:
Intent intent = new Intent(MainActivity.this, SerializableActivity.class); Person person = new Person(); person.setName("如花"); person.setAge(18); intent.putExtra("put_ser_test", person); startActivity(intent);
在数据接收界面:
Intent intent = getIntent(); Person per = (Person)intent.getSerializableExtra("put_ser_test"); mTvDate.setText("名字:" + per.getName() + "\n" + "年龄:" + per.getAge());
Serializable 到此完成,没什么好解释的。Serializable的优点就是简单。
(二)Parcelable, 速度至上
Parcelable在数据传递的使用方面,和Serializable一模一样。在数据的接收方面,唯一的区别在于Serializable是intent.getSerializableExtra,而Parcelable是getIntent().getParcelableExtra。它们在使用上最大的区别,是实体类:
先看代码:
public class Pen implements Parcelable{ private String color; private int size; // 系统自动添加,给createFromParcel里面用 protected Pen(Parcel in) { color = in.readString(); size = in.readInt(); } public static final Creator<Pen> CREATOR = new Creator<Pen>() { /** * * @param in * @return * createFromParcel()方法中我们要去读取刚才写出的name和age字段, * 并创建一个Person对象进行返回,其中color和size都是调用Parcel的readXxx()方法读取到的, * 注意这里读取的顺序一定要和刚才写出的顺序完全相同。 * 读取的工作我们利用一个构造函数帮我们完成了 */ @Override public Pen createFromParcel(Parcel in) { return new Pen(in); // 在构造函数里面完成了 读取 的工作 } //供反序列化本类数组时调用的 @Override public Pen[] newArray(int size) { return new Pen[size]; } }; @Override public int describeContents() { return 0; // 内容接口描述,默认返回0即可。 } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(color); // 写出 color dest.writeInt(size); // 写出 size } // ======分割线,写写get和set //个人自己添加 public Pen() { } //个人自己添加 public Pen(String color, int size) { this.color = color; this.size = size; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } }
当你实现Parcelable接口后,Android Studio(as)就会提示你重写describeContents方法和writeToParcel方法。在writeToParcel方法中,需要写出
dest.writeString(color); // 写出 color dest.writeInt(size); // 写出 size
写完后,发现as依旧提示报错:
你根据提示操作后,选择Add Parcelable Implementation,发现as自动添加了以下代码:
public static final Creator<Pen> CREATOR = new Creator<Pen>() { /** * * @param in * @return * createFromParcel()方法中我们要去读取刚才写出的name和age字段, * 并创建一个Person对象进行返回,其中color和size都是调用Parcel的readXxx()方法读取到的, * 注意这里读取的顺序一定要和刚才写出的顺序完全相同。 * 读取的工作我们利用一个构造函数帮我们完成了 */ @Override public Pen createFromParcel(Parcel in) { return new Pen(in); // 在构造函数里面完成了 读取 的工作 } //供反序列化本类数组时调用的 @Override public Pen[] newArray(int size) { return new Pen[size]; } };
也就是,随便一个类实现了Parcelable接口一开始就会变成这样子。Parcelable方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了。
使用Parcelable在代码上的确比Serializable要麻烦一些,但也没有想象中那么麻烦,因为系统已经帮我们做了很多事情。接下来,我们只需要写写我们自己需要的构造方法,写一下私有变量的get和set就行了。
整个实现Parcelable的实体类就完成了。其实,还有更简单的方法.就是使用as的android parcelable code generator插件,一键生成。如何生成的教程,网上有很多。比如这篇[点击跳转]。(http://blog.csdn.net/kroclin/article/details/40902721)
按照教程操作,生成的代码和上述手写的一模一样。如果您是第一次使用android parcelable code generator插件,我简单说一下生成步骤:
1.写出变量
private String color; private int size;
2.点击鼠标右键:
选择Genetate,然后选择Parcelable就可。截图如下:
这里,我们将实现Parcelable接口的方法进行简单说明一下:
方法 | 功能 | 标识符 |
---|---|---|
createFromParcel(Parcel source) | 从序列化后的对象中创建原始对象 | |
newArray(int size) | 创建指定长度的原始对象数组 | |
Pen(Parcel in) | 从序列化后的对象中创建原始对象 | |
writeToParcel(Parcel out,int flags) | 将当前对象写入序列化结构中 | PARCALABLE_WRITE_RETURN_VALUE |
describeContents | 返回当前对象的内容描述,几乎所有情况都返回0,仅在当前对象中存在文件描述符时返回1 | CONTENTS_FILE_DESCRIPTOR |
三.原理与性能比较
Serializable的有点在于你只需要对某个类以及它的属性实现Serializable 接口即可。Serializable 接口是一种标识接口(marker interface),这意味着无需实现方法,Java便会对这个对象进行高效的序列化操作。而缺点是:这种方法是使用了反射,序列化的过程较慢。这种机制会在序列化的时候创建许多的临时对象,容易触发垃圾回收。而Parcelable方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了。根据 google 工程师的说法,这些代码将会运行地特别快。原因之一就是我们已经清楚地知道了序列化的过程,而不需要使用反射来推断。同时为了更快地进行序列化,对象的代码也需要高度优化。
那到底Parcelable比Serializable快多少呢?我们来进行测试:
(一)测试方法
通过将一个对象放到一个bundle里面然后调用Bundle#writeToParcel(Parcel, int)方法来模拟传递对象给一个activity的过程,然后再把这个对象取出来。在一个循环里面运行1000 次。
两种方法分别运行10次来减少内存整理,cpu被其他应用占用等情况的干扰。
参与测试的对象就是上面代码中的Person和 Pen。
在多种Android软硬件环境上进行测试(LG Nexus 4 – Android 4.2.2、Samsung Nexus 10 – Android 4.2.2、HTC Desire Z – Android 2.3.3)
(二)测试结果
测试结果如下图:由此可以得出: Parcelable 比 Serializable快了10多倍。有趣的是,即使在Nexus 10这样性能强悍的硬件上,一个相当简单的对象的序列化和反序列化的过程要花将近一毫秒。
四.总结
如果您想让您开发的程序运行更流程,您需要多花点时间来实现 Parcelable ,因为这将会为你对象的序列化过程快10多倍,而且占用较少的资源。加上现在已经有了插件,实现Parcelable接口的实体类代码也可以一键生成,Parcelable 的缺点就显得微不足道了。区别 | Serializable | Parcelable |
---|---|---|
所属API | JAVA API | Android SDK API |
原理 | 序列化和反序列化过程需要大量的I/O操作 | 序列化和反序列化过程不需要大量的I/O操作 |
开销 | 开销大 | 开销小 |
效率 | 低 | 很高 |
使用场景 | 序列化到本地或者通过网络传输 | 内存序列化 |
点击下载源码
关于我:
1.一个热爱Android编程,也乐于分享、交友的菜鸟。
我的QQ:984992087 微信:gaolhjy
2.GitHub地址 点击跳转
您的start就是我分享的最大动力。
参考资料:
序列化Serializable和Parcelable的理解和区别
Android系统中Parcelable和Serializable的区别
相关文章推荐
- Android 序列化Serializable和Parcelable的理解和区别
- Android中Serializable和Parcelable序列化的区别
- Android中序列化的Parcelable与Serializable区别及其AS插件
- 序列化Serializable和Parcelable的理解和区别
- Android -- 序列化Parcelable与Serializable区别及用法
- Android面试笔记——序列化Serializable和Parcelable的理解
- 序列化Serializable和Parcelable的理解和区别
- Android序列化Serializable和Parcelable区别
- Android数据序列化之对Parcelable和Serializable的理解
- 序列化Serializable和Parcelable的理解和区别
- Android中的Parcelable接口和Serializable用法和区别
- Android Serializable和Parcelable的区别和用法
- Android Parcelable和Serializable的区别,androidparcelable
- 安卓中序列化Serializable和Parcelable区别和使用,intent间传递
- 理解序列化 Serializable 和 Parcelable
- 【转】Android Parcelable和Serializable的区别
- 序列化Parcelable和Serializable接口的区别
- Android Serializable与Parcelable原理与区别
- 【Android】【序列化】Parcelable And Serializable
- Android系统中Parcelable和Serializable的区别