我们向第三方开发者公开AIDL服务。我们想从此服务返回parcelable对象,但我们担心向后兼容性。通过这个,我的意思是根据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
}
类C
的解组失败(我尝试使用Parcel.writeList()
和Parcel.writeParcelableArray()
)。
这种情况似乎无法想象,这种情况无法处理。当然,我们可以按原样保留旧的binder接口,并创建一个新的binder接口,该接口返回带有附加字段的新类的对象,但是对于返回-t-changing类的服务,这将导致复杂的混乱。例如,接口1.0返回Person
。现在我们添加一个字段,我们有一个新的binder接口2.0,它返回Person2
个对象,依此类推。
这让我们使用一些更宽容的格式,比如JSON,来传递IPC数据。
有什么建议吗? 感谢。
答案 0 :(得分:2)
根据Parcelable
和AIDL接口的版本N编译的客户端需要Service
支持,直到宇宙热死亡,而不仅仅是N + 1,除非你想要打破一大堆客户或有能力迫使这些开发人员更新他们的应用程序。
当然,我们可以按原样保留旧的活页夹界面
对AIDL本身的任何更改意味着您需要新协议版本的新服务端点,更不用说更改Parcelable
定义了。
例如,接口1.0返回一个Person。现在我们添加一个字段,我们有一个新的binder接口2.0,它返回Person2对象,依此类推。
或者:
第一次正确使用,以便您没有“经常更改”的公共API,或
使用Bundle
作为“经常更改”的方面,因为Bundle
是稳定的(例如,Person
有properties
{{1}你希望在每隔几年的主要API版本之间使用你的公共API,或者
首先使用Bundle
,因此您的API更多地传递属性包,或
切换到Bundle
,尽管它可能有点慢,因为它有版本控制的概念,或者
完全转储绑定模式并使用命令模式,附加项作为属性包
JSON的替代方法大致类似于首先使用Serializable
,除了您不必使用Bundle
编写自己的编组/解编码代码。
Bundle
因速度原因特别避免版本控制。这就是为什么Parcelable
不是为持久存储而设计的,当类可能在保存数据和读入数据之间发生变化时。
答案 1 :(得分:0)
如果您只是在AIDL中添加其他方法(不修改现有方法),则可以将其他方法作为最后方法放在AIDL文件中并且这不会破坏现有的依赖应用程序(仍然是根据您之前的AIDL定义构建的)。 您的新服务应用(使用添加的方法)适用于旧应用和新应用(根据您的新AIDL定义构建)。在新的应用程序中,只要他们与支持旧AIDL定义的旧版服务进行通信,他们就需要捕获IllegalArgumentException。在我的例子中,我提供了一个包装IPC调用的客户端类,因此应用程序实际上不执行调用,我在那里执行异常捕获,只记录情况并从该方法返回null。
答案 2 :(得分:0)
Android 10中现在通过Stable AIDL支持AIDL的版本控制。