使用Parcelable而不是序列化对象的好处
据我所知, Bundle
和Parcelable
属于Android执行序列化的方式,例如用于在活动之间传递数据。 但是我想知道,如果在将业务对象的状态保存到内部存储器的情况下使用Parcelable
而不是经典序列化有什么好处? 它会比传统方式更简单还是更快? 我应该在哪里使用经典的序列化和哪里更好地使用捆绑?
从“Pro Android 2”
注意:看到Parcelable可能触发了这个问题,为什么Android不使用内置的Java序列化机制? 事实certificate,Android团队得出的结论是,Java中的序列化太慢,不能满足Android的进程间通信要求。 所以团队build立了Parcelable解决scheme。 Parcelable方法要求你明确地序列化你的类的成员,但是最后你可以更快的对你的对象进行序列化。
同时也意识到,Android提供了两种机制,允许您将数据传递给另一个进程。 首先是使用意图将一个包传递给一个活动,另一个是将一个Parcelable传递给一个服务。 这两种机制不可互换,不应混淆。 也就是说,Parcelable并不意味着被传递给一个活动。 如果你想开始一个活动并传递一些数据,可以使用一个包。 Parcelable只能用作AIDL定义的一部分。
Serializable
在Android上非常慢。 实际上在许多情况下边界线是无用的。
Parcel
和Parcelable
的速度非常快,但是它的文档说明你不能将它用于通用序列化存储,因为实现因Android的不同版本而不同(即操作系统更新可能会破坏依赖它的应用程序)。
以合理的速度将数据序列化到存储的问题的最佳解决scheme是自行开发。 我个人使用我自己的一个实用程序类,它有一个与Parcel
类似的接口,并且可以非常有效地序列化所有标准types(以types安全为代价)。 这是它的一个删节的版本:
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++; } } }
看看Parcelable比Serializable有多快。
从为什么我们喜欢可爱的
从Parcelable与Serializable
如果为了存储目的而需要序列化,但是为了避免由Serializable接口引起的reflection的速度损失,您应该使用Externalizable接口明确地创build自己的序列化协议。
当正确实现时,这与Parcelable的速度相匹配,并且还考虑了不同版本的Android和/或Java平台之间的兼容性。
这篇文章可能会清除一些事情:
Java中的Serializable和Externalizable有什么区别?
在旁注中,它也是许多基准testing中速度最快的序列化技术,击败了Kryo,Avro,Protocol Buffers和Jackson(json):
http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking
看来现在的差异并不那么明显,至less不是在你自己的活动之间运行。
根据本网站上显示的testing,Parcelable在最新的设备(如nexus 10)上快10倍左右,而老设备上的快17倍(如欲望Z)
所以这是由你来决定是否值得。
也许对于相对较小和简单的类,可序列化是好的,其余的,你应该使用Parcelable
Parcelable主要涉及使用Binder基础结构的IPC,数据以Parcel的forms传递。
由于Android依赖于Binder的大部分(即使不是全部)IPC任务,所以在大多数地方,特别是在框架中实现Parcelable是有意义的,因为如果需要的话,它允许将对象传递给另一个进程。 它使对象“可移动”。
但是,如果您有一个非Android特定的业务层,它广泛使用可序列化来保存对象状态,只需要将它们存储到文件系统,那么我认为可序列化是好的。 它允许避免Parcelable锅炉代码。
基于这篇文章http://www.mooproductions.org/node/6?page=5 Parcelable应该更快。
在文章中没有提到的是,我不会喋喋不休,可序列化的对象将在远程服务的AIDL中工作。
我只是使用GSON – >序列化到JSONstring – >从JSONstring恢复对象。
另外,Parcelable提供了自定义实现,用户通过覆盖writeToParcel()获得机会来包装他的每个对象。但是,序列化不会将这个自定义实现作为传递数据的方式涉及到JAVAreflectionAPI。