Android系统中Parcelable和Serializable的区别

进行Android开发的时候,我们都知道不能将对象的引用传给Activities或者Fragments,我们需要将这些对象放到一个Intent或者Bundle里面,然后再传递。

通过Android的API,我们知道有两种选择,即在传递对象时,需要对我们的对象进行 Parcelable 或者Serializable化。作为Java开发者,相信大家对Serializable 机制有一定了解,那为什么还需要 Parcelable呢?

为了回答这个问题,让我们分别来看看这两者的差异。

Serializable, 简单易用

public class SerializableDeveloper implements Serializable

String name;

int yearsOfExperience;

List<Skill> skillSet;

float favoriteFloat;

static class Skill implements Serializable {

String name;

boolean programmingRelated;

}

}

serializable的迷人之处在于你只需要对某个类以及它的属性实现Serializable 接口即可。Serializable 接口是一种标识接口(marker interface),这意味着无需实现方法,Java便会对这个对象进行高效的序列化操作。

这种方法的缺点是使用了反射,序列化的过程较慢。这种机制会在序列化的时候创建许多的临时对象,容易触发垃圾回收。

Parcelable, 速度至上

// access modifiers, accessors and regular constructors ommited for brevity

class ParcelableDeveloper implements Parcelable {

String name;

int yearsOfExperience;

List<Skill> skillSet;

float favoriteFloat;

ParcelableDeveloper(Parcel in) {

this.name = in.readString();

this.yearsOfExperience = in.readInt();

this.skillSet = new ArrayList<Skill>();

in.readTypedList(skillSet, Skill.CREATOR);

this.favoriteFloat = in.readFloat();

}

void writeToParcel(Parcel dest, int flags) {

dest.writeString(name);

dest.writeInt(yearsOfExperience);

dest.writeTypedList(skillSet);

dest.writeFloat(favoriteFloat);

}

int describeContents() {

return 0;

}

static final Parcelable.Creator<ParcelableDeveloper> CREATOR

= new Parcelable.Creator<ParcelableDeveloper>() {

ParcelableDeveloper createFromParcel(Parcel in) {

return new ParcelableDeveloper(in);

}

ParcelableDeveloper[] newArray(int size) {

return new ParcelableDeveloper[size];

}

};

static class Skill implements Parcelable {

String name;

boolean programmingRelated;

Skill(Parcel in) {

this.name = in.readString();

this.programmingRelated = (in.readInt() == 1);

}

@Override

void writeToParcel(Parcel dest, int flags) {

dest.writeString(name);

dest.writeInt(programmingRelated ? 1 : 0);

}

static final Parcelable.Creator<Skill> CREATOR

= new Parcelable.Creator<Skill>() {

Skill createFromParcel(Parcel in) {

return new Skill(in);

}

Skill[] newArray(int size) {

return new Skill[size];

}

};

@Override

int describeContents() {

return 0;

}

}

}

根据 google 工程师的说法,这些代码将会运行地特别快。原因之一就是我们已经清楚地知道了序列化的过程,而不需要使用反射来推断。同时为了更快地进行序列化,对象的代码也需要高度优化。

因此,很明显实现Parcelable并不容易。实现Parcelable接口需要写大量的模板代码,这使得对象代码变得难以阅读和维护。

速度测试

当然,我们还是想知道到底Parcelable相对于Serializable要快多少。

测试方法

通过将一个对象放到一个bundle里面然后调用Bundle#writeToParcel(Parcel, int)方法来模拟传递对象给一个activity的过程,然后再把这个对象取出来。

在一个循环里面运行1000 次。

两种方法分别运行10次来减少内存整理,cpu被其他应用占用等情况的干扰。

参与测试的对象就是上面代码中的SerializableDeveloper 和 ParcelableDeveloper。

在多种Android软硬件环境上进行测试

LG Nexus 4 – Android 4.2.2

Samsung Nexus 10 – Android 4.2.2

HTC Desire Z – Android 2.3.3

NEXUS 10

Serializable: 1.0004ms,  Parcelable: 0.0850ms – 提升10.16倍。

NEXUS 4

Serializable: 1.8539ms – Parcelable: 0.1824ms – 提升11.80倍。

DESIRE Z

Serializable: 5.1224ms – Parcelable: 0.2938ms – 提升17.36倍。

由此可以得出: Parcelable 比 Serializable快了10多倍。有趣的是,即使在Nexus 10这样性能强悍的硬件上,一个相当简单的对象的序列化和反序列化的过程要花将近一毫秒。

总结

如果你想成为一个优秀的软件工程师,你需要多花点时间来实现 Parcelable ,因为这将会为你对象的序列化过程快10多倍,而且占用较少的资源。

但是大多数情况下, Serializable 的龟速不会太引人注目。你想偷点懒就用它吧,不过要记得serialization是一个比较耗资源的操作,尽量少使用。

如果你想要传递一个包含许多对象的列表,那么整个序列化的过程的时间开销可能会超过一秒,这会让屏幕转向的时候变得很卡顿。

英文原文:developerphil

译文来源:Android Cool Posts

链接:http://greenrobot.me/devpost/android-parcelable-serializ

时间: 2024-12-18 14:05:36

Android系统中Parcelable和Serializable的区别的相关文章

Android系统中Parcelable和Serializable的区别,自动化实现Parcelable接口的插件

Parcelable和Serializable的区别 参考地址:http://greenrobot.me/devpost/android-parcelable-serializable/ 由于最终的区别在于Parcelable的序列化速度远远高于Serializable,故本人更倾向于使用Parcelable,但是Parcelable接口实现起来较为复杂,所以很多人不愿意写. 但是在Android Studio和Idea中有自动生成Parcelable代码模板的插件,相当实用. 可参考如下地址使

Android系统中的dp和px的转换

android系统中DP和SP的转化:1.首先分析TypedValue.java 可以调用以下代码获得dp的值 TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20,getResources().getDisplayMetrics()); public static float applyDimension(int unit, float value,DisplayMetrics metrics) { switch (unit) {

Android系统中添加一个产品----图文详解

本文本着开源的精神介绍如何向一个Android系统中添加一个产品的整个过程,按照以下过程笔者有理由相信每个将要从事本行业的人都可以完成,其实添加一个产品并不难,难的是对其相关硬件的修改,好了废话不多说. 首先我们要创建一个属于自己产品的目录,这里以WY_device为例,以WY作为产品的名字. 首先从已经存在的产品中拷贝一个以产品的名字为名的.mk文件,修改为自己的.mk文件,在这里为WY.mk 对其进行如下的修改: 然后添加AndroidProducts.mk  这是添加产品的配置文件名路径,

Android系统中的广播(Broadcast)机制简要介绍和学习计划

在Android系统中,广播(Broadcast)是在组件之间传播数据(Intent)的一种机制:这些组件甚至是可以位于不同的进程中,这样它就像Binder机制一样,起到进程间通信的作用:本文通过一个简单的例子来学习Android系统的广播机制,为后续分析广播机制的源代码作准备. 在Android系统中,为什么需要广播机制呢?广播机制,本质上它就是一种组件间的通信方式,如果是两个组件位于不同的进程当中,那么可以用Binder机制来实现,如果两个组件是在同一个进程中,那么它们之间可以用来通信的方式

自己动手清除Android系统中的不良程序

陈跃峰 2014/6/29 最近在使用我的Nexus7时,总是经常莫名其妙的弹出一些广告弹窗,还会自动下载一些应用程序,还会在桌面上生成一个叫做"精彩应用"的图标,这个快捷方式关联的程序显示的内容和广告内容是一致的,很是烦人,使用360手机卫士和乐安全都发现不了这个不良程序,所以就自己动手来清除这个程序. 由于Nexus 7平时用于测试程序,安装的应用很多,手动删除了一些可疑的应用以后还是不行,猜测是某些app可能被人篡改了,就不再去删除app了,而把目光转向了桌面快捷方式上. 既然生

Android系统中设置TextView的行间距(非行高)

Android系统中TextView默认显示中文时会比较紧凑,不是很美观.为了让每行保持一定的行间距,可以设置属性android:lineSpacingExtra或android:lineSpacingMultiplier. 关于Android下TextView中文换行问题,可查看Android自定义view-文本自动换行. 1.android:lineSpacingExtra设置行间距,如”3dp”. 2.android:lineSpacingMultiplier设置行间距的倍数,如”1.2″

向Android系统中添加模块及产品流程

 添加Android模块  一.基础知识: (1)在Android系统中,编译都是以模块(而不是文件)作为单位的,每个模块都有一个唯一的名称: (2)为了将模块编译到Android系统中,每个模块都需要一个专门的Make文件,也即是"Android.mk"文件: 二.实现hello.c 模块的编写  1. 如在 hardware/test目录下,编写hello.c 2. 在hardw/test目录下,编写Android.mk Android.mk编写的步骤: (1)设置当前模块的编译路

Android 系统中,那些能大幅提高工作效率的 API 汇总(持续更新中...)

前言 "条条大路通罗马."工作中,实现某个需求的方式往往不是唯一的,这些不同实现方式不仅表现在代码质量上,还影响着我们的工作效率.就像,在 Android 系统中,总有那么一些鲜为人知的 API 能够减少我们很多零碎的工作量.于是,就想凭着一些经验,整理一些常用的,找个地方归纳总结,也供日后翻阅. getResources().getIdentifier(String name, String defType, String defPackage) 根据资源名称获取资源 id.正常情况

AIDL在android系统中的作用

AIDL,Android Interface definition language的缩写,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口.最近看了下AIDL在Android系统中的用法,在网上看到很多初学的朋友不太明白AIDL的实际作用,android提供了很多进程间通信的组件,像action.broadcast.contentprovide都可以实现进程间的通信,为什么还要用AIDL这个东西呢?我在android源码中实现了一个自己写的AIDL例子,用以