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

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

本文翻译自:http://www.developerphil.com/parcelable-vs-serializable/

【安卓开发】Android系统中Parcelable和Serializable的区别的更多相关文章

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

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

  2. Android系统中Parcelable和Serializable的区别

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

  3. .Net程序员之不学Java做安卓开发:Android Studio中的即时调试窗口

    对学.Net的人来说,JAVA开发是一场噩梦. .net中的即时窗口,调试时直接在里面写代码,对程序中的各种方法/属性进行调用,很方便. Android Studio中找了好久,参考如下网址,也有类似 ...

  4. Parcelable和Serializable的区别

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

  5. 在Eclipse+ADT中开发Android系统的内置应用

    转自:  http://www.iteye.com/topic/1050439 在Eclipse+ADT中开发Android系统的内置应用 Android系统内置有:Browser(浏览器).Mms( ...

  6. android系统中如何通过程序打开某个AccessibilityService

    android系统中如何通过程序打开某个AccessibilityService(系统辅助服务)? 通常的做法是注册AccessibilityService(辅助服务)后跳转到设置启动服务页面引导用户 ...

  7. AIDL在android系统中的作用

    AIDL,Android Interface definition language的缩写,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口.最近看了下AIDL在A ...

  8. Android系统中的6种模式

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

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

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

随机推荐

  1. java中包的定义

    对包中的java程序进行编译(cmd) 编译:javac -d . Test.java 执行:java com.java.demo.Test package com.java public class ...

  2. 页面js脚本与img等资源的下载顺序问题。

    引言问题 <img src="background.jpg"><script src="test.js"></script> ...

  3. How to preview html file in our browser at sublime text?

    sublime preview html.md open In Browser what should we do if we want to preview html file in our bro ...

  4. [LeetCode] Monotone Increasing Digits 单调递增数字

    Given a non-negative integer N, find the largest number that is less than or equal to N with monoton ...

  5. [LeetCode] Valid Parenthesis String 验证括号字符串

    Given a string containing only three types of characters: '(', ')' and '*', write a function to chec ...

  6. 关于Ueditor存储在mysql"UTF-8"乱码的问题

    关于Ueditor存储在mysql"UTF-8"乱码的问题 首先小编要声明之前出乱码的原因,mysql 字段设置的BLOB类型 紧接着我们要先确认两件事: 1.首先要确认你的mys ...

  7. servlet之隐藏域

    隐藏域的实现, 商品对象 package app02b;public class Customer {        private int id;    private String name;   ...

  8. 网络安全实验室_上传关writeup

    请上传一张jpg格式的图片 先传个图片码试试 我肯定乖嘛(#`Д´)ノ 气到改后缀 请上传一张jpg格式的图片 我猜是00截断,不信来试试 先在赋值1.php .jpg,接着去hex中找到空格改成00 ...

  9. [WC 2011]Xor

    Description Input 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 ...

  10. bzoj 1272: [BeiJingWc2008]Gate Of Babylon

    Description Solution 如果没有限制,答案就是 \(\sum_{i=0}^{m}C(n+i-1,i)\) 表示枚举每一次取的个数,且不超过 \(m\),方案数为可重组合 发现这个东西 ...