Parcelableでオブジェクトを一時的に保存する


今回はParcelableインタフェースを用いて、インスタンスの状態を保存する方法を説明します。

状態の保存と言うとシリアライズを思い浮かべる方もいると思いますがシリアライズは永続化を目的としていますが、Parcelableはプロセス間通信のときなど、一時的に状態を保存したいときに利用します。

シリアライズの方法に関しては以下の記事を参考にしてください。

それでは続きでParcelableインタフェースを用いて、インスタンスの状態を保存する方法を説明します。

大まかな流れ

Parcelableインターフェースを実装したクラスの作成の大まかな流れは以下の通りです。詳細は後述します。

  1. インタフェースの抽象メソッドを実装
  2. Parcelable.CreatorクラスをCREATORという名前でStaticフィールドに用意
  3. 状態の復元を行うコンストラクタ作成

Parcelableインタフェース実装したクラスの作成(保存部分)

Parcelableはインタフェースなので実装 (implements)して利用します。

Parcelableインタフェースの実装すべきメソッドは

  • abstract int describeContents()
  • abstract void writeToParcel(Parcel dest, int flags)

の2つです。

describeContentsメソッドは通常0を返すように実装します。FileDescriptorを配置する場合はParcelableインタフェースの定数であるCONTENTS_FILE_DESCRIPTORを返すようにします。

writeToParcelメソッドでメンバを保存します。

public class SampleParcelable implements Parcelable {
    private int mData;
    private String mString;

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mData);
        out.writeString(mString);
    }

Parcelableインタフェース実装したクラスの作成(復元部分)

Parcelableインタフェースを実装したクラスは、Parcelable.Creatorインタフェースを実装するオブジェクトであるCREATORという名前のStatic(静的)フィールドを持つ必要があります。

これは下記のサンプルを見てもらうのが一番だと思います。

public static final Parcelable.Creator CREATOR
			= new Parcelable.Creator() {
	public SampleParcelable createFromParcel(Parcel in) {
		return new SampleParcelable(in);
	}

	public SampleParcelable[] newArray(int size) {
		return new SampleParcelable[size];
	}
};

ここでParcelを引数とするコンストラクタを呼び出していることが分かります。

return new SampleParcelable(in);

つまりParcelを引数とするコンストラクタを実装することも必要で、そのコンストラクタの中で復元を行います。
注意点はwriteToParcelで保存した順番で読み出す必要があることです。

private SampleParcelable(Parcel in) {
	// writeToParcelで保存した順番で読み出す必要がある
    mData = in.readInt();
    mString = in.readString();
}

状態の保存、復元の例

実際にParcelableを使う場面としては冒頭で書いたプロセス間通信以外にActivityのライフサイクルの中でも使うことがあります。
プリミティブ型ではなく、オブジェクトを保存したい時に利用出来ます。
public class MainActivity extends Activity {
	private SampleParcelable mSampleParcelable;

	〜省略〜

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		outState.putParcelable("parcelable", mSampleParcelable);
	}

    @Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		super.onRestoreInstanceState(savedInstanceState);
		mSampleParcelable = savedInstanceState.getParcelable("parcelable");
	}
}

以上、Parcelableでオブジェクトを一時的に保存する方法でした