我们向第三方开发人员公开一个aidl服务。我们想从这个服务返回可分包的对象,但是我们担心向后兼容性。我的意思是,根据Parcelable的N版编译的客户机和根据N+1版编译的服务必须协同工作。
从我的测试来看,对于简单的平面对象(仅限于简单类型字段),只要在流的末尾打包新字段,向后兼容是可能的……例如。,

in.writeInt(field1);
in.writeInt(field2); // new field

然而,当涉及到复杂的物体时,事情就会爆炸。例如,
class D implements Parcelable {
  int field1;
}

class C implements Parcelable {
  List<D> ds;
}

如果第二个字段添加到类D
class D implements Parcelable {
  int field1;
  int field2; // new field
}

类的解组失败(我尝试使用CParcel.writeList())。
这件事办不好,简直不可思议。当然,我们可以保留原来的绑定器接口,并创建一个新的绑定器接口,该接口返回带有附加字段的新类的对象,但是对于返回经常更改的类的服务,这将导致复杂的混乱。例如,接口1.0返回一个Parcel.writeParcelableArray()。现在我们添加了一个字段,并且我们有了一个新的绑定接口2.0,它返回Person对象等。
这使得我们可以使用一些更宽容的格式,比如json,来传递ipc数据。
有什么建议吗?
谢谢。

最佳答案

根据Parcelable版本n和aidl接口编译的客户端需要Service的支持,直到宇宙的热死,而不仅仅是在n+1之前,除非你想破坏一堆客户端或是迫使那些开发人员更新他们的应用程序。
当然,我们可以把旧的活页夹界面保持原样
对aidl本身的任何更改都意味着您需要新协议版本的新服务端点,更不用说对Parcelable定义的更改了。
例如,接口1.0返回一个人。现在我们添加了一个字段,并且我们有了一个新的绑定接口2.0,它返回person2对象等。
要么:
第一次就做对了,这样就不会有“经常变化”的公共api,或者
对于“经常变化”的方面,使用aBundle,因为Bundle是稳定的(例如,aPerson有一个propertiesBundle用于您希望在每隔几年的主要api修订中使用到您的公共api的东西),或者
首先使用Bundle,这样您的api就更容易传递属性包,或者
切换到Serializable,尽管它可能有点慢,因为它有版本控制的概念,或者
完全转储绑定模式并使用命令模式,并使用extras作为属性包
您对json的替代方法大致类似于首先使用Bundle,只是您不必为自己的封送/解组代码操心。
Bundle由于速度原因特别避免版本控制。这就是为什么Parcelable不是为持久存储而设计的,因为类可能在保存数据和读入数据之间发生变化。

10-07 19:31
查看更多