关闭

Android系统中Parcelable和Serializable的区别

标签: android
205人阅读 评论(0) 收藏 举报

转载,原文 :Android系统中Parcelable和Serializable的区别 

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

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

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

Serializable, 简单易用

  1. // access modifiers, accessors and constructors omitted for brevity
  2. public class SerializableDeveloper implements Serializable
  3.     String name;
  4.     int yearsOfExperience;
  5.     List<Skill> skillSet;
  6.     float favoriteFloat;
  7.  
  8.     static class Skill implements Serializable {
  9.         String name;
  10.         boolean programmingRelated;
  11.     }
  12. }

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

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

Parcelable, 速度至上

  1. // access modifiers, accessors and regular constructors ommited for brevity
  2. class ParcelableDeveloper implements Parcelable {
  3.     String name;
  4.     int yearsOfExperience;
  5.     List<Skill> skillSet;
  6.     float favoriteFloat;
  7.  
  8.     ParcelableDeveloper(Parcel in) {
  9.         this.name = in.readString();
  10.         this.yearsOfExperience = in.readInt();
  11.         this.skillSet = new ArrayList<Skill>();
  12.         in.readTypedList(skillSet, Skill.CREATOR);
  13.         this.favoriteFloat = in.readFloat();
  14.     }
  15.  
  16.     void writeToParcel(Parcel dest, int flags) {
  17.         dest.writeString(name);
  18.         dest.writeInt(yearsOfExperience);
  19.         dest.writeTypedList(skillSet);
  20.         dest.writeFloat(favoriteFloat);
  21.     }
  22.  
  23.     int describeContents() {
  24.         return 0;
  25.     }
  26.  
  27.  
  28.     static final Parcelable.Creator<ParcelableDeveloper> CREATOR
  29.             = new Parcelable.Creator<ParcelableDeveloper>() {
  30.  
  31.         ParcelableDeveloper createFromParcel(Parcel in) {
  32.             return new ParcelableDeveloper(in);
  33.         }
  34.  
  35.         ParcelableDeveloper[] newArray(int size) {
  36.             return new ParcelableDeveloper[size];
  37.         }
  38.     };
  39.  
  40.     static class Skill implements Parcelable {
  41.         String name;
  42.         boolean programmingRelated;
  43.  
  44.         Skill(Parcel in) {
  45.             this.name = in.readString();
  46.             this.programmingRelated = (in.readInt() == 1);
  47.         }
  48.  
  49.         @Override
  50.         void writeToParcel(Parcel dest, int flags) {
  51.             dest.writeString(name);
  52.             dest.writeInt(programmingRelated ? 1 : 0);
  53.         }
  54.  
  55.         static final Parcelable.Creator<Skill> CREATOR
  56.             = new Parcelable.Creator<Skill>() {
  57.  
  58.             Skill createFromParcel(Parcel in) {
  59.                 return new Skill(in);
  60.             }
  61.  
  62.             Skill[] newArray(int size) {
  63.                 return new Skill[size];
  64.             }
  65.         };
  66.  
  67.         @Override
  68.         int describeContents() {
  69.             return 0;
  70.         }
  71.     }
  72. }


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

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

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:32458次
    • 积分:659
    • 等级:
    • 排名:千里之外
    • 原创:29篇
    • 转载:41篇
    • 译文:0篇
    • 评论:0条