据我了解,Bundle
它Parcelable
属于Android执行序列化的方式。例如,它用于在活动之间传递数据。但是我想知道,例如,如果将Parcelable
业务对象的状态保存到内部存储器中,使用经典序列化代替传统序列化是否有任何好处?它会比经典方式更简单或更快速吗?我应该在哪里使用经典序列化,哪里可以更好地使用包?
据我了解,Bundle
它Parcelable
属于Android执行序列化的方式。例如,它用于在活动之间传递数据。但是我想知道,例如,如果将Parcelable
业务对象的状态保存到内部存储器中,使用经典序列化代替传统序列化是否有任何好处?它会比经典方式更简单或更快速吗?我应该在哪里使用经典序列化,哪里可以更好地使用包?
Answers:
来自“ Pro Android 2”
注意:看到Parcelable可能已经触发了一个问题,为什么Android不使用内置的Java序列化机制?事实证明,Android团队得出的结论是,Java的序列化速度太慢,无法满足Android的进程间通信要求。因此,团队构建了Parcelable解决方案。Parcelable方法要求您显式地序列化类的成员,但是最后,您可以更快地序列化对象。
还应认识到Android提供了两种机制,可让您将数据传递到另一个进程。第一个是使用意图将捆绑包传递给活动,第二个是将Parcelable传递给服务。这两种机制是不可互换的,不应混淆。也就是说,Parcelable并非要传递给活动。如果要启动活动并将其传递一些数据,请使用捆绑包。可打包仅用于AIDL定义的一部分。
getBundle
方法,然后从writeToParcel
as中调用该方法,dest.writeBundle(getBundle());
并且对象中的两个选项都自动可用。这里提到了一些有趣的用于活动对象的Parcel功能:developer.android.com/reference/android/os/Parcel.html
Serializable
在Android上速度缓慢。实际上,在许多情况下,边界线无用。
Parcel
并且Parcelable
是飞驰快,但它的文档说,你不能将它用于通用序列化存储,因为执行不同的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++;
}
}
}
如果出于存储目的需要序列化,但又希望避免Serializable接口引起的反射速度损失,则应该使用Externalizable接口显式创建自己的序列化协议。
如果正确实施,则可以与Parcelable的速度相匹配,并且可以说明不同版本的Android和/或Java平台之间的兼容性。
本文还可以解决这些问题:
Java中的Serializable和Externalizable有什么区别?
在旁注中,它也是许多基准测试中最快的序列化技术,击败了Kryo,Avro,Protocol Buffers和Jackson(json):
如今,这种差异似乎并不那么明显,至少在您自己的活动之间运行它时,这种差异并不明显。
根据该网站上显示的测试,在最新设备(例如nexus 10)上,Parcelable的速度大约是10倍,而在旧设备(例如欲望Z)上,Parcelable的速度大约是17倍。
因此由您决定是否值得。
也许对于相对较小和简单的类,Serializable就可以,其余的,您应该使用Parcelable
Parcelable主要与使用Binder基础结构的IPC有关,其中数据作为Parcels传递。
由于Android大部分(即使不是全部)IPC任务都依赖于Binder,因此在大多数地方(尤其是在框架中)实现Parcelable是有意义的,因为它允许在需要时将对象传递给另一个进程。它使对象“可运输”。
但是,如果您有一个非Android专用的业务层,该层广泛使用可序列化的对象来保存对象状态,并且只需要将它们存储到文件系统中,那么我认为可序列化就可以了。它可以避免使用可拆分样板代码。
根据本文http://www.mooproductions.org/node/6?page=5可 打包应该更快。
本文中未提及的是,我不认为可序列化的对象将在AIDL中适用于远程服务。
另外,Parcelable还提供了自定义实现,用户可以通过重写writeToParcel()来打包每个对象的机会,但是序列化没有此自定义实现,因为其传递数据的方式涉及JAVA反射API。