Parcelable
オブジェクトと Bundle
オブジェクトは、IPC / Binder トランザクションやインテントを持つアクティビティ間などのプロセス境界で使用したり、設定変更前後の一時的な状態を格納したりすることが想定されています。このページでは、Parcelable
オブジェクトと Bundle
オブジェクトの使用に際しての推奨事項とおすすめの方法について説明します。
注: Parcel
は汎用のシリアル化メカニズムではないため、Parcel
データをディスクに保存したり、ネットワーク経由で送信したりしないでください。
アクティビティ間でデータを送信する
新しいアクティビティの開始時にアプリが Intent
オブジェクトを作成して startActivity(android.content.Intent)
で使用するとき、putExtra(java.lang.String, java.lang.String)
メソッドを使用してパラメータを渡すことができます。
次のコード スニペットに、この処理を実行する方法の例を示します。
Kotlin
val intent = Intent(this, MyActivity::class.java).apply { putExtra("media_id", "a1b2c3") // ... } startActivity(intent)
Java
Intent intent = new Intent(this, MyActivity.class); intent.putExtra("media_id", "a1b2c3"); // ... startActivity(intent);
OS は、インテントの基となる Bundle
をパーセル化します。次に、OS は新しいアクティビティを作成し、データのパーセル化を解除して、新しいアクティビティにインテントを渡します。
Bundle
クラスを使用して、OS にとって既知のプリミティブを Intent
オブジェクトに設定することをおすすめします。Bundle
クラスは、パーセルを使用したマーシャリングとアンマーシャリングに対して高度に最適化されています。
複合オブジェクトや複雑なオブジェクトをアクティビティ間で送信するメカニズムが必要な場合があります。その場合、カスタムクラスで Parcelable を実装し、適切な writeToParcel(android.os.Parcel, int)
メソッドを用意してください。また、Parcelable.Creator
インターフェースを実装する null でない CREATOR
と呼ばれるフィールドも用意する必要があります。このインターフェースの createFromParcel()
メソッドは、Parcel
を変換して現在のオブジェクトに戻すために使用されます。
詳細については、Parcelable
オブジェクトのリファレンス ドキュメントをご覧ください。
インテント経由でデータを送信する場合は、データサイズを数 KB に制限してください。送信するデータ量が多すぎると、TransactionTooLargeException
例外がスローされます。
プロセス間でデータを送信する
プロセス間でデータを送信する方法は、アクティビティ間で行う方法と似ています。しかし、プロセス間で送信する場合、カスタムの Parcleable は使用しないことをおすすめします。カスタムの Parcelable
オブジェクトをアプリから別のアプリに送信する場合、送信側と受信側の両方のアプリに正確に同じバージョンのカスタムクラスが必ず存在する必要があります。そのため、通常は両方のアプリで共通のライブラリを使用します。なお、システムにカスタムの Parcelable を送ろうとするとエラーが発生する可能性があります。これは、システムが既知のものでないクラスをアンマーシャリングできないためです。
たとえば、AlarmManager
クラスを使用してアラームを設定し、アラーム インテントにカスタムの Parcelable
を使用したとします。アラームが生じると、エクストラのインテントの Bundle
を変更され、繰り返し回数が追加されます。この変更により、カスタムの Parcelable
がエクストラから削除されます。その結果、変更されたアラーム インテントを受信したときにアプリがクラッシュする可能性があります。これは、アプリがすでに存在しなくなったエクストラ データの受信を想定しているためです。
Binder トランザクション バッファには固定のサイズ制限(現在 1 MB)があり、これは処理中のトランザクションすべてで共有されます。この制限は、アクティビティごとのレベルではなくプロセスレベルであるため、これらのトランザクションには、onSaveInstanceState や startActivity、システムとのすべてのやり取りなど、アプリ内のすべての Binder トランザクションが含まれます。サイズ制限を超えると、TransactionTooLargeException がスローされます。
saveInstanceState の特定のケースでは、データ量を少なくする必要があります。これは、ユーザーがそのアクティビティに戻る可能性がある限り(アクティビティのプロセスが強制終了された場合も含む)、システム プロセスが与えられたデータを保持する必要があるためです。状態を保存するデータは 50k 未満にすることをおすすめします。
注: Android 7.0(API レベル 24)以降では、ランタイム例外として TransactionTooLargeException がスローされます。これより前のバージョンの Android では、logcat に警告が表示されるだけです。