镜像类和实现Parcelable的最佳方法是什么?
原因是因为我正在使用一个库,但我还需要广播一个对象,为了让我这样做,我需要实现Parcelable而不编辑库中的原始类?
更新:
答案 0 :(得分:0)
编辑:
所以我查看了pires/obd-java-api on GitHub,现在我看到了你的问题:OBDCommand
类是一个抽象类,它有四个抽象子类和四十三个具体子类。
让人惊讶。
使用反射为所有这些类创建Parcel
工厂不是我想要做的事情。所以我认为你最好的选择是:
与Paulo Pires讨论如何OBDCommand
实施Serializable
。在OBDCommand
实现Serializable
后,有人应该遍历所有子类并确保所有字段都可以序列化,并且所有瞬态字段都标记为transient
。
然后你可以有这样一个类:
public class ParcelableOBDCommand implements Parcelable {
private OBDCommand mObdCommand;
public ParcelableOBDCommand(OBDCommand obdCommand) {
mObdCommand = obdCommand;
}
public OBDCommand getObdCommand() {
return mObdCommand;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(baos);
out.writeObject(mObdCommand);
dest.writeInt(baos.toByteArray().length);
dest.writeByteArray(baos.toByteArray());
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
public static final Parcelable.Creator<ParcelableOBDCommand> CREATOR = new Parcelable.Creator<ParcelableOBDCommand>() {
@Override
public ParcelableOBDCommand createFromParcel(Parcel source) {
try {
byte[] bytesIn = new byte[source.readInt()];
source.readByteArray(bytesIn);
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytesIn));
return new ParcelableOBDCommand((OBDCommand) in.readObject());
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
@Override
public ParcelableOBDCommand[] newArray(int size) {
return new ParcelableOBDCommand[size];
}
};
}
请注意,这仅在OBDCommand
实施Serializable
时才有效。
还要注意Parcelable
的全部目的是摆脱Serializable
的反射开销,所以我们在这里打败了整个目的。 &#34; OBD命令&#34;实际上只是少数几个字节,因此Paulo可能更好地了解如何序列化这一类的类。另外,这取决于您在广播服务中使用课程的方式,也许您不需要将Parcel
中的所有内容保存到您的服务广播中。但策略是:实现(纯Java,非Android)方式在OBDCommand
级别读取/写入OBDCommand
子类,然后编写使用纯Java的Parcelable
类引擎盖下的机制。
这是一个可以访问源代码的开源库吗?
您可以创建一个Parcelable
实现,该实现使用反射来读取对象字段值并将它们写入Parcel
,Parcelable.Creator
工厂可以使用Class.newInstance()
重新创建对象并使用反射将Parcel
中的值写入新对象。缺点:将库更新为新版本可能会破坏您的Parcelable
代码。但是,如果您必须反序列化使用早期版本存储的任何对象,至少可以从Parcel
读取旧版本的值并将其写入新版本,解决您的问题&# 39; t的值为。
这不是开源的,但您要镜像的类实现了Serializable
吗?
您可以将对象序列化为ByteArrayOutputStream
,然后将字节写入Parcel
。然后Parcelable.Creator
工厂将读取字节并创建一个ByteArrayInputStream
,从中可以反序列化对象。缺点:如果您的Parcel
存储在某个位置(例如数据库中),并且库已更新为新版本,则如果该类尚未处理反序列化旧版本,则尝试反序列化存储的对象将失败
以上都不是?
您可以反编译和grok该类,然后使用反射来读取和写入字段值,就像使用开源策略一样。缺点:你必须反编译并参加课程。每次发布新库以检查是否有任何更改时,您都必须这样做。
如果您想要更详细的答案,请在问题中添加更多详细信息:哪个类,哪个库,定期修订等等。