4

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;
}

2 番目のフィールドが class に追加された場合D

class D implements Parcelable {
  int field1;
  int field2; // new field
}

クラス s のアンマーシャリングがC失敗します ( and を使用しParcel.writeList()てみParcel.writeParcelableArray()ました)。

これは、このケースを処理できないことはほとんど考えられないようです。確かに、古いバインダー インターフェースをそのまま残して、新しいクラスのオブジェクトを追加のフィールドと共に返す新しいバインダー インターフェースを作成することはできますが、頻繁に変化するクラスを返すサービスの場合、これは複雑な混乱を招きます。たとえば、インターフェイス 1.0 は を返しますPersonPerson2ここでフィールドを追加し、オブジェクトを返す新しいバインダー インターフェイス 2.0 を用意しました。

これにより、JSON などのより寛容な形式を使用して IPC データを渡すことができます。

助言がありますか?

4

3 に答える 3

3

のバージョン N および AIDL インターフェースに対してコンパイルされたクライアントは、N+1 までだけでなく、ユニバースの熱的消滅までParcelableによってサポートされる必要があります。Serviceアプリを更新します。

確かに、古いバインダー インターフェイスはそのままにしておくことができます

AIDL 自体への変更は、Parcelable定義の変更は言うまでもなく、新しいプロトコル バージョン用の新しいサービス エンドポイントが必要であることを意味します。

たとえば、インターフェイス 1.0 は Person を返します。ここでフィールドを追加し、Person2 オブジェクトを返す新しいバインダー インターフェイス 2.0 を用意しました。

また:

  • 「頻繁に変化する」パブリック API を使用しないように、最初から正しく設定するか、

  • は安定しているBundleため、「頻繁に変化する」側面には a を使用します (たとえば、aには、数年ごとの主要な API リビジョンの間にパブリック API にグロムしたいものがあります)。BundlePersonproperties Bundle

  • Bundleそもそもa を使用して、API がより多くのプロパティ バッグを通過するようにするか、

  • Serializableバージョン管理の概念があるため、おそらく少し遅いですが、に切り替えます。または

  • バインディング パターンを完全にダンプし、プロパティ バッグとして機能するエクストラを使用して、コマンド パターンを使用します。

JSON の代替手段はBundle、最初に a を使用することにほぼ似ていますが、Bundle.

Parcelable特に、速度上の理由からバージョン管理を回避します。そのParceableため、データが保存されたときとデータが読み込まれたときとの間でクラスが変更される可能性がある場合、永続的なストレージ用に設計されていません。

于 2013-08-13T00:07:45.363 に答える