从现有库镜像类并实现Parcelable

时间:2015-09-15 13:37:07

标签: android class

镜像类和实现Parcelable的最佳方法是什么?

原因是因为我正在使用一个库,但我还需要广播一个对象,为了让我这样做,我需要实现Parcelable而不编辑库中的原始类?

更新:

  • 该库是opensource,但它是用纯java编写的。
  • 我更喜欢不在自己的类中进行更改,因为我承诺使用此repo,并且希望保持库纯java。
  • 该库是pires的OBD2 java库。
  • 该类是OBDCommand.java

1 个答案:

答案 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实现,该实现使用反射来读取对象字段值并将它们写入ParcelParcelable.Creator工厂可以使用Class.newInstance()重新创建对象并使用反射将Parcel中的值写入新对象。缺点:将库更新为新版本可能会破坏您的Parcelable代码。但是,如果您必须反序列化使用早期版本存储的任何对象,至少可以从Parcel读取旧版本的值并将其写入新版本,解决您的问题&# 39; t的值为。

  • 这不是开源的,但您要镜像的类实现了Serializable吗?

    您可以将对象序列化为ByteArrayOutputStream,然后将字节写入Parcel。然后Parcelable.Creator工厂将读取字节并创建一个ByteArrayInputStream,从中可以反序列化对象。缺点:如果您的Parcel存储在某个位置(例如数据库中),并且库已更新为新版本,则如果该类尚未处理反序列化旧版本,则尝试反序列化存储的对象将失败

  • 以上都不是?

    您可以反编译和grok该类,然后使用反射来读取和写入字段值,就像使用开源策略一样。缺点:你必须反编译并参加课程。每次发布新库以检查是否有任何更改时,您都必须这样做。

如果您想要更详细的答案,请在问题中添加更多详细信息:哪个类,哪个库,定期修订等等。