Parcelable と Bundle

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

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 に警告が表示されるだけです。