2011-04-05 143 views
93

据我所知,BundleParcelable属于Android执行序列化的方式。它用于例如在活动之间传递数据。但是我想知道,如果在将业务对象的状态保存到内部存储器的情况下使用Parcelable而不是经典序列化有什么好处?它会比传统方式更简单还是更快?我应该在哪里使用经典序列化以及哪里更好地使用捆绑包?基于本文http://www.mooproductions.org/node/6?page=5 Parcelable应该快上使用Parcelable代替序列化对象的好处

回答

97

从“临安卓2”

注:看到Parcelable可能引发的问题,为什么不Android的使用 内置Java序列化机制?事实证明,在 Android团队得出的结论 在Java中的序列化速度太慢,满足Android的 进程间通信 要求。所以团队构建了Parcelable解决方案。该 Parcelable方法需要 你明确你的序列化类的成员,但最终, 你会得到更快的 系列化的对象。

还意识到Android提供了两种机制,允许您将 数据传递给另一个 进程。第一种是使用意图将一个包传递给一个活动,第二个是将一个 Parcelable传递给一个服务。这两种机制是不可互换的, 不应该是 困惑。也就是说,Parcelable并不意味着被传递给 活动。如果您想要启动 某个活动并将其传递给一些数据,请使用一个包。可分包的意思是 仅作为 的一部分用于AIDL定义。

+8

什么是“Pro Android 2”? – 2012-04-02 15:55:02

+1

Reto Meier专业Android 2应用程序开发 http://www.amazon。com/Professional-Android-Application-Development-Programmer/dp/0470565527 – mparaz 2012-06-12 03:03:05

+75

第二段不是真的,你可以将一个Parcelable作为参数传递给使用该包的活动...... – Ixx 2012-06-22 19:46:18

1

在文章中没有提及,就是我不htink可序列化对象将在AIDL工作的远程服务。

4

Parcelable使用Binder基础设施,其中数据为Parcels传递主要涉及IPC。

由于Android对于大多数(即使不是全部)IPC任务依赖于Binder,所以在大多数地方,特别是在框架中实现Parcelable是有意义的,因为如果需要的话,它允许将对象传递给另一个进程。它使物体“可运输”。

但是,如果你有大量使用serializables保存对象的状态,只需要将它们存储到文件系统中的非特异性Android的业务层,那么我认为序列化是好的。它允许避免Parcelable锅炉代码。

+0

您希望在saya文件系统中存储实际对象的例子是什么?为什么不简单地获取对象内容并将实际内容存储在文件中。以JSON为例,甚至是xml。您可以使用JSON或XML格式保存对象,也可以使用POJO/Entity类型来保存对象,这些类型构造了一个典型的数据对象,这些数据对象主要由State构成,并为该状态创建了getter和setter。这样就不需要序列化对象来存储它们,因为所有你关心的是对象状态 – jonney 2013-04-04 23:33:47

22

Serializable在Android上显得很慢。事实上,许多情况下边界线无用。

ParcelParcelable是飞驰的快,但它的documentation说,你不能将它用于通用序列化存储,因为实现与不同版本的Android(即操作系统的更新可能会破坏它依赖于它的应用程序而异)。

以合理的速度将数据序列化到存储的问题的最佳解决方案是滚动您自己的数据。我个人使用我自己的实用程序类中的一个,它具有与Parcel类似的接口,并且可以非常有效地序列化所有标准类型(以牺牲类型安全性为代价)。下面是它的一个删节版:

public interface Packageable { 
    public void readFromPackage(PackageInputStream in) throws IOException ; 
    public void writeToPackage(PackageOutputStream out) throws IOException ; 
} 


public final class PackageInputStream { 

    private DataInputStream input; 

    public PackageInputStream(InputStream in) { 
     input = new DataInputStream(new BufferedInputStream(in)); 
    } 

    public void close() throws IOException { 
     if (input != null) { 
      input.close(); 
      input = null; 
     }  
    } 

    // Primitives 
    public final int readInt() throws IOException { 
     return input.readInt(); 
    } 
    public final long readLong() throws IOException { 
     return input.readLong(); 
    } 
    public final long[] readLongArray() throws IOException { 
     int c = input.readInt(); 
     if (c == -1) { 
      return null; 
     } 
     long[] a = new long[c]; 
     for (int i=0 ; i<c ; i++) { 
      a[i] = input.readLong(); 
     } 
     return a; 
    } 

... 

    public final String readString() throws IOException { 
     return input.readUTF(); 
    } 
    public final <T extends Packageable> ArrayList<T> readPackageableList(Class<T> clazz) throws IOException { 
     int N = readInt(); 
     if (N == -1) { 
      return null; 
     } 
     ArrayList<T> list = new ArrayList<T>(); 
     while (N>0) { 
      try { 
       T item = (T) clazz.newInstance(); 
       item.readFromPackage(this); 
       list.add(item); 
      } catch (InstantiationException e) { 
       e.printStackTrace(); 
      } catch (IllegalAccessException e) { 
       e.printStackTrace(); 
      } 
      N--; 
     } 
     return list; 
    } 

} 



public final class PackageOutputStream { 

    private DataOutputStream output; 

    public PackageOutputStream(OutputStream out) { 
     output = new DataOutputStream(new BufferedOutputStream(out)); 
    } 

    public void close() throws IOException { 
     if (output != null) { 
      output.close(); 
      output = null; 
     } 
    } 

    // Primitives 
    public final void writeInt(int val) throws IOException { 
     output.writeInt(val); 
    } 
    public final void writeLong(long val) throws IOException { 
     output.writeLong(val); 
    } 
    public final void writeLongArray(long[] val) throws IOException { 
     if (val == null) { 
      writeInt(-1); 
      return; 
     } 
     writeInt(val.length); 
     for (int i=0 ; i<val.length ; i++) { 
      output.writeLong(val[i]); 
     } 
    } 

    public final void writeFloat(float val) throws IOException { 
     output.writeFloat(val); 
    } 
    public final void writeDouble(double val) throws IOException { 
     output.writeDouble(val); 
    } 
    public final void writeString(String val) throws IOException { 
     if (val == null) { 
      output.writeUTF(""); 
      return; 
     } 
     output.writeUTF(val); 
    } 

    public final <T extends Packageable> void writePackageableList(ArrayList<T> val) throws IOException { 
     if (val == null) { 
      writeInt(-1); 
      return; 
     } 
     int N = val.size(); 
     int i=0; 
     writeInt(N); 
     while (i < N) { 
      Packageable item = val.get(i); 
      item.writeToPackage(this); 
      i++; 
     } 
    } 

} 
+1

使用这个自定义类和仅仅实现Externalizable接口并且做同样的事情有什么区别? – Carrotman42 2012-06-29 12:41:36

+0

使用类型安全的“Bundle”来序列化数据不是更好吗?如上所述,你可以通过一个Bundle的'writeBundle'方法传递一个Bundle。 – mikebabcock 2012-09-26 16:08:22

+1

Bundle序列化字段名称以及...它不适合数千个对象。 – 2012-09-27 08:08:24

9

如果你需要,即存储的目的序列化,但要避免被序列化界面发生反射的速度损失,你应该明确地创建与外部化自己的序列化协议接口。

正确实施后,这与Parcelable的速度相匹配,并且还考虑了不同版本的Android和/或Java平台之间的兼容性。

本文可能澄清一些事情,以及:

What is the difference between Serializable and Externalizable in Java?

在旁注,它也是许多基准测试速度最快的序列化技术,击败KRYO,Avro公司,协议缓冲器和杰克逊(JSON):

http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking

7

看来,时下的差别并不那么都明显,至少是在你自己的活动之间运行。

据对this website显示测试,Parcelable是最新的设备(如Nexus 10)快约10倍,约17快于旧的(如欲望Z)

所以它是由你来决定如果它值得的话。

也许比较小和简单的类,序列化是好的,其他的,你应该使用Parcelable

+0

我认为你说这笔钱的差距正在缩小。然而,我发现使用serializable可以在封送字节数组的大小方面更有效率,并且可以帮助避免TransactionTooLargeException。我很想听听你对这个(我的)博客帖子的评论http://nemanjakovacevic.net/blog/english/2015/03/24/yet-another-post-on-serializable-vs-parcelable/ – 2015-03-25 01:09:00

+0

好吧,你可以将巨大的内存消耗对象放在一个静态变量上,并在您获取它时将其设置为null(例如onCreate)。缺点是它不支持多进程,并且这样做有点肮脏。如果你想传递一个大的位图,不知道是否是这种情况。 – 2015-03-25 06:22:19

1

我只是用GSON - >连载到JSON字符串 - >从JSON对象恢复字符串。

+0

这对小对象来说很好,当你有大量的对象时,每个对象都有很多属性。 – Nickmccomb 2017-05-29 23:58:13

0

另外,Parcelable提供了自定义实现,其中用户通过重写writeToParcel()获得了对每个对象进行包裹的自定义实现。但是,序列化不会将此自定义实现作为传递数据的方式涉及JAVA反射API。