转载:https://greenrobot.me/devpost/android-parcelable-serializable/

进行Android开发的时候,我们都知道不能将对象的引用传给Activities或者Fragments,我们需要将这些对象放到一个Intent或者Bundle里面,然后再传递。
通过Android的API,我们知道有两种选择,即在传递对象时,需要对我们的对象进行 Parcelable 或者Serializable化。作为Java开发者,相信大家对Serializable 机制有一定了解,那为什么还需要 Parcelable呢?

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

Serializable, 简单易用

 
1
2
3
4
5
6
7
8
9
10
11
12
// access modifiers, accessors and constructors omitted for brevity
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, 速度至上

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// 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

结果


parcelable-vs-serializable

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是一个比较耗资源的操作,尽量少使用。

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

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

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

    Parcelable和Serializable的区别 参考地址:http://greenrobot.me/devpost/android-parcelable-serializable/ 由于最终的区 ...

  2. 【安卓开发】Android系统中Parcelable和Serializable的区别

    http://greenrobot.me/devpost/android-parcelable-serializable/ 进行Android开发的时候,我们都知道不能将对象的引用传给Activiti ...

  3. Parcelable和Serializable的区别

      一.Android为什么要序列化?什么是序列化,怎么进行序列化 why 为什么要了解序列化?—— 进行Android开发的时候,无法将对象的引用传给Activities或者Fragments,我们 ...

  4. [原创]Android系统中常用JAVA类源码浅析之HashMap

    由于是浅析,所以我只分析常用的接口,注意是Android系统中的JAVA类,可能和JDK的源码有区别. 首先从构造函数开始, /** * Min capacity (other than zero) ...

  5. Android系统中的dp和px的转换

    android系统中DP和SP的转化:1.首先分析TypedValue.java 可以调用以下代码获得dp的值 TypedValue.applyDimension(TypedValue.COMPLEX ...

  6. 在Android系统中修改Android.mk使其同时编译rgb2565和rgb2888(向out/host/linux-x86/bin/下新增加一个工具命令)【转】

    本文转载自:http://blog.csdn.net/mu0206mu/article/details/7514559 在Android系统中修改android.mk使其同时编译rgb2565和rgb ...

  7. Android系统中的6种模式

    Android系统中的6种模式 1:一般启动模式(normal mode):    功能是正常启动手机,方法为关机状态下按电源键启动. 2:安全模式(safe mode):    此模式和正常启动一样 ...

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

    在Android系统中,广播(Broadcast)是在组件之间传播数据(Intent)的一种机制:这些组件甚至是可以位于不同的进程中,这样它就像Binder机制一样,起到进程间通信的作用:本文通过一个 ...

  9. Android系统中 setprop,getprop,watchprops命令的使用

    如:在frameworks/opt/net/ims/src/java/com/android/ims/ImsManager.java if (SystemProperties.get("pe ...

随机推荐

  1. jquery ajax请求 清除缓存

    使用jquery里load方法或者ajax调用页面的时候会存在cache的问题,清除cache的方法: 调用jQuery.ajaxSetup ({cache:false}) 方法即可.

  2. 解析UML9种图的作用

    本文和大家重点讨论一下UML9种图的概念,UML中有五类图,共有9种图形,每种图形都有各自的特点,下面就让我们一起来看一下这些图形特点的详细介绍吧. UML9种图简介 1.用例图 说明的是谁要使用系统 ...

  3. ActivityManager: Warning: Activity not started, its current task has been brought to the front 的的问题

    运行android程序的时候提示:ActivityManager: Warning: Activity not started, its current task has been brought t ...

  4. Content-Type

    HTTP Content-type .*( 二进制流,不知道下载文件类型) application/octet-stream .txt text/plain 没有csv这种类型

  5. 屏蔽页面js报的错误

    有时候,某些js的错误,确实没有什么大影响,但是这个又实在没办法. 一般,下下策采取 <script language="javascript"> function k ...

  6. 对Spring IoC容器实现的结构分析

    本文的目标:从实现的角度来认识SpringIoC容器. 观察的角度:从外部接口,内部实现,组成部分,执行过程四个方面来认识SpringIoC容器. 本文的风格:首先列出SpringIoC的外部接口及内 ...

  7. webdriver(python)学习笔记一

    最近有python开发的项目,也正打算要学习自动化与python语言.因此想通过学习python版本的webdriver来一同学习. 学习过程中参考资料有乙醇的博客:https://github.co ...

  8. Headmaster's Headache

    题意: s门课程,现任老师有m个给出工资,和他们能教的课,现在有n个应聘的老师,给出费用和能教的课程标号,求使每门课都至少有两个老师教的最小花费 分析: n个老师选或不选有背包的特征,n很小想到用状压 ...

  9. acdream 1056 (黑白染色)

    题意:给你一些关系,每个关系是两只马的名字,表示这两个马不能在一个分组里,问你能否将这些马分成两组. 黑白染色,相邻的点染不同颜色.bfs搞即可,水题. /* * this code is made ...

  10. 《Python CookBook2》 第一章 文本 - 去字符串两端的空格 && 合并字符串 && 将字符串逐字符或者逐词反转

    去字符串两端的空格 任务: 获得一个开头和末尾都没有多余空格的字符串. 解决方案: 字符串对象的lstrip.rstrip和strip 方法正是为这种任务而设计的.这几个方法都不需要参数,它们会直接返 ...