26

シリアル化可能なデータをインテント エクストラとして渡すことに関して私が観察している動作は非常に奇妙です。見逃していないものがあるかどうかを明確にしたかっただけです。

だから私がやろうとしていたことは、次のアクティビティを開始するために作成した にインスタンスActivtyAを入れることです - 。LinkedListintentActivityB

LinkedList<Item> items = (some operation);
Intent intent = new Intent(this, ActivityB.class);
intent.putExtra(AppConstants.KEY_ITEMS, items);

onCreateof で、次のようにエクストラActivityBを取得しようとしました-LinkedList

LinkedList<Item> items = (LinkedList<Item>) getIntent()
                             .getSerializableExtra(AppConstants.KEY_ITEMS);

これを実行すると、上記の行ClassCastExceptionで in ActivityB, を繰り返し取得しました。基本的に、例外は私がArrayList. ArrayList上記のコードを代わりに受け取るように変更すると、すべてが正常に機能しました。

シリアライズ可能な List 実装を渡すときに、これが Android で予期される動作であるかどうか、既存のドキュメントからはわかりません。あるいは、私がしていることに根本的な問題があるのか​​もしれません。

ありがとう。

4

3 に答える 3

51

なぜこれが起こっているのかはわかりますが、あなたはそれを気に入らないでしょう;-)

まず、背景情報を少し説明します。

のエクストラは、基本的にキーと値のペアでIntentある Androidです。だからあなたが何かをするときBundleHashMap

intent.putExtra(AppConstants.KEY_ITEMS, items);

Android はエクストラ用に新しいものを作成し、キーがあり、値が項目(LinkedList オブジェクト) でBundleある場所にマップ エントリを追加します。BundleAppConstants.KEY_ITEMS

これで問題ありません。コードの実行後にエクストラ バンドルを確認すると、LinkedList. 興味深い部分は次のとおりです...

エクストラを含むインテントで呼び出す場合startActivity()、Android はキーと値のペアのマップからエクストラをバイト ストリームに変換する必要があります。基本的にBundleをシリアル化する必要があります。別のプロセスでアクティビティを開始する可能性があるため、これを行う必要があります。そのためには、新しいプロセスでオブジェクトを再作成できるように、バンドル内のオブジェクトをシリアル化/逆シリアル化する必要があります。また、後で必要になった場合に Intent を再生成できるように、Android は一部のシステム テーブルに Intent の内容を保存するため、これを行う必要があります。

をバイト ストリームにシリアル化するためにBundle、バンドル内のマップを調べて、各キー/値のペアを取得します。次に、各「値」(オブジェクトの一種) を取得し、最も効率的な方法でシリアル化できるように、そのオブジェクトの種類を判別しようとします。これを行うために、既知のオブジェクト タイプのリストに対してオブジェクト タイプをチェックします。「既知のオブジェクト タイプ」のリストにはIntegerLongStringMapBundle残念ながら も含まれていますList。そのため、オブジェクトがList( を含むさまざまな種類があるLinkedList) である場合、それをシリアル化し、 type のオブジェクトとしてマークしますList

がデシリアライズされるときBundle、つまり: これを行うとき:

LinkedList<Item> items = (LinkedList<Item>)
        getIntent().getSerializableExtra(AppConstants.KEY_ITEMS);

のタイプArrayListのすべてのオブジェクトを生成します。BundleList

Android のこの動作を変更するためにできることは実際には何もありません。少なくともこれで、なぜこれを行うのかがわかります。

ご存知のように、私は実際にこの動作を検証する小さなテスト プログラムを作成し、マップをバイト ストリームに変換するときにParcel.writeValue(Object v)呼び出されるメソッドのソース コードを調べました。Bundle

重要な注意:Listはインターフェースであるため、これは、 に配置したものを実装するすべてのクラスがとしてList出力Bundleされることを意味しますArrayList。が「既知のオブジェクト タイプ」のリストに含まれていることも興味深い点Mapです。これは、どの種類のMapオブジェクトを に入れてもBundle(たとえばTreeMap、 、またはインターフェイスSortedMapを実装する任意のクラス)、常に から を取得することを意味します。それ。MapHashMap

于 2012-09-06T17:35:58.667 に答える