[Android]Bundleに独自クラスを格納する方法(Parcelableインターフェイス)

投稿者:

Androidではアプリ同士やアクティビティ同士で情報をやり取りするときBandleをよく使う。

bundle.putInt(KEY1, data);
bundle.putString(KEY2, text);

int data = bundle.getInt(KEY1);
String text = bundle.getString(KEY2);

数値や文字列など基本的なデータをBundleに格納するときは上記のように書けばよい。

では独自クラスのデータをBundleに入れたいときはどうしたらいいのだろうか。

bundle.putInt(KEY1, customClass.getData1());
bundle.putInt(KEY2, customClass.getData2());

こんな感じでメンバ変数の値をいちいち取り出して格納することもできるが、メンバ変数が多いととてもめんどくさい。

さらにBundleを受け取った側では

CastomClass customClass = new CastomClass();
customClass.setData1(bundle.getInt(KEY1));
customClass.setData2(bundle.getInt(KEY2));

という風にオブジェクトを作り直さなきゃならない。

でも独自クラスにParcelableインターフェイスを実装すれば、オブジェクト自体をBundleに入れることができる。

以下はCarMakerという独自クラスにParcelableインターフェイスを実装した例である。

public class CarMaker implements Parcelable {

    //メンバ変数
    private int code;
    private String name;
    private String country;

    //コンストラクタ
    public CarMaker () {}    //空のコンストラクタ

    public CarMaker (int code, String name, String country) {
        this.code = code;
        this.name = name;
        this.country = country;
    }

    //ゲッター

    public int getCode() {
        return code;
    }

    public String getName() {
        return name;
    }

    public String getCountry() {
        return country;
    }

    //セッター

    public void setCode(int code) {
        this.code = code;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    /////  AndroidStudioが自動生成 /////

    protected CarMaker(Parcel in) {
        code = in.readInt();
        name = in.readString();
        country = in.readString();
    }

    public static final Creator CREATOR = new Creator() {
        @Override
        public CarMaker createFromParcel(Parcel in) {
            return new CarMaker(in);
        }

        @Override
        public CarMaker[] newArray(int size) {
            return new CarMaker[size];
        }
    };

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(code);
        dest.writeString(name);
        dest.writeString(country);
    }

    ///////////////////////////////////////
}

例の中に「AndroidStudioが自動生成」というコメントがあるが、これ以降のコードは自分では一切書いていない。なのでいまいち理解度が低いのだが、大体以下のような感じであろう。

Parcelableインターフェイスで実装しなければならないのは以下の二つ。

public int describeContents()
public void writeToParcel(Parcel dest, int flags)

describeContents()がreturnでゼロを返すのはお約束のようである。
writeToParcel()はメンバ変数をParcelクラスに流すためにあるようだ。

staticなCreatorクラスの変数CREATORはCarMakerのインスタンスを再作成するために使われている模様。これもお約束のようだ。

CarMaker(Parcel in)はCarMakerクラスのコンストラクタだが、Parcelクラスからデータを取得してインスタンスを作成するためのもの。外部からは見えず、CREATEORから呼ばれるだけである。CREATORの付属品みたいなものだからこれも必須かな。

結局のところ、Parcelというオブジェクトに一時的にデータを保存してインスタンスは破棄、Bundleから取り出されるされるときにインスタンスを復元しているようである。メンバ変数をいちいち取得してBundleに放り込むやり方と大して変わらないが、使う側からしたらオブジェクトそのものを格納して取り出しているように見えるというわけだ。

Parcelableを実装したら

bundle.putParcelable(KEY1, carMaker);  //オブジェクト単体
bundle.putParcelableArray(KEY2, carMakers);  //オブジェクトの配列
bundle.putParcelableArrayList(KEY3, carMakerArrayList);  //オブジェクトのArrayList

CarMaker carMaker = bundle.getParcelable(KEY1);
CarMaker[] carMakers = bundle.getParcelableArray(KEY2);
ArrayList<CarMaker> carMakerArrayList = bundle.getParcelableArrayList(KEY3);

こんな感じで格納と取得を行なう。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください