LoginSignup
26
25

More than 5 years have passed since last update.

Parcelableを作るのが面倒臭いので簡単にする

Posted at

面倒臭いので簡単にする

AndroidでParcelableを作るのはいろいろと面倒臭いです。Java言語の仕様的にParcelableインターフェースの必須メソッドを実装するのは仕方がないとしても、項目数が多いとその数だけParcelへのParcelable.CreatorとwriteToParcelを書かないといけないのでかなり手間です。そのParcelable.CreatorとwriteToParcelの部分のコードをAPT(Annotation Processing Tool)で自動生成するツール、CatHandsGendroidを作りました。

どう簡単したいか

一番面倒くさいのはParcelable.CreatorとwriteToParcelのコードを項目ごとに書かないといけないところです。特に項目の数は比較的頻繁に更新しますし、項目を追加したけどそれらのコードを追加し忘れると不具合の原因になります。この面倒臭いところをAPTを使ってCatHandsGendroidに自動生成してもらい、その生成されたコードに繋ぐようにします。

使い方:APTの設定編

 導入方法はこちらと同じになります。

使い方:モデルクラスの作成編

手順は次のようになります。

  1. アノテーションとして「@DataModel(genParcelFunc=true, genDbFunc=false)」を付加する
  2. 生成されたParcelable.CreatorとwriteToParcelのコードを繋ぐ

例えばこんなモデルクラスがあるとします。

@DataModel(genParcelFunc=true, genDbFunc=false)
public class MyParcelModel {
    private String strValue1;
    private String strValue2;
    private int intValue1;
    private int intValue2;
    private int doubleValue1;
    private int doubleValue2;
    /* getterとsetteerは省略 */
}

アノテーションを付けると次のようなコードが生成されます。

public class MyParcelModelCatHands {
    public static final IAccessor<String> ACCESSOR_STR_VALUE1;
    public static final IAccessor<String> ACCESSOR_STR_VALUE2;
    public static final IAccessor<Integer> ACCESSOR_INT_VALUE1;
    public static final IAccessor<Integer> ACCESSOR_INT_VALUE2;
    public static final IAccessor<Integer> ACCESSOR_DOUBLE_VALUE1;
    public static final IAccessor<Integer> ACCESSOR_DOUBLE_VALUE2;
    static {
        ACCESSOR_STR_VALUE1 = Accessors.StringAccessor.createAccessor(String.class);
        ACCESSOR_STR_VALUE2 = Accessors.StringAccessor.createAccessor(String.class);
        ACCESSOR_INT_VALUE1 = Accessors.PrimitiveIntegerAccessor.createAccessor(Integer.class);
        ACCESSOR_INT_VALUE2 = Accessors.PrimitiveIntegerAccessor.createAccessor(Integer.class);
        ACCESSOR_DOUBLE_VALUE1 = Accessors.PrimitiveIntegerAccessor.createAccessor(Integer.class);
        ACCESSOR_DOUBLE_VALUE2 = Accessors.PrimitiveIntegerAccessor.createAccessor(Integer.class);
    }
    public static final android.os.Parcelable.Creator<MyParcelModel> CREATOR = new android.os.Parcelable.Creator<MyParcelModel>() {
        @Override
        public MyParcelModel createFromParcel(android.os.Parcel in) {
            MyParcelModel dest = new MyParcelModel();
            readFromParcel(dest, in);
            return dest;
        }
        @Override
        public MyParcelModel[] newArray(int size) {
            return new MyParcelModel[size];
        }
    };
    public static void readFromParcel(MyParcelModel dest, android.os.Parcel in) {
        dest.setStrValue1(ACCESSOR_STR_VALUE1.readFromParcel(in));
        dest.setStrValue2(ACCESSOR_STR_VALUE2.readFromParcel(in));
        dest.setIntValue1(ACCESSOR_INT_VALUE1.readFromParcel(in));
        dest.setIntValue2(ACCESSOR_INT_VALUE2.readFromParcel(in));
        dest.setDoubleValue1(ACCESSOR_DOUBLE_VALUE1.readFromParcel(in));
        dest.setDoubleValue2(ACCESSOR_DOUBLE_VALUE2.readFromParcel(in));
    }
    public static void writeToParcel(MyParcelModel src, android.os.Parcel out, int flags) {
        ACCESSOR_STR_VALUE1.writeToParcel(out, src.getStrValue1());
        ACCESSOR_STR_VALUE2.writeToParcel(out, src.getStrValue2());
        ACCESSOR_INT_VALUE1.writeToParcel(out, src.getIntValue1());
        ACCESSOR_INT_VALUE2.writeToParcel(out, src.getIntValue2());
        ACCESSOR_DOUBLE_VALUE1.writeToParcel(out, src.getDoubleValue1());
        ACCESSOR_DOUBLE_VALUE2.writeToParcel(out, src.getDoubleValue2());
    }
}

このコードはParcelableを実装するときに必要で面倒臭い原因であるParcelable.CreatorとwriteToParcelのコードを含んでいます。
この2つのコードを元のモデルクラスに繋ぎます。

@DataModel(genParcelFunc=true, genDbFunc=false)
public class MyParcelModel implements Parcelable {
    // CREATEを繋ぐ
    public static final Creator<MyParcelModel> CREATOR = 
            MyParcelModelCatHands.CREATOR;

    // writeToParcelを繋ぐ
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        MyParcelModelCatHands.writeToParcel(this, dest, flags);
    }
    @Override
    public int describeContents() {
        return 0;
    }

    private String strValue1;
    private String strValue2;
    private int intValue1;
    private int intValue2;
    private int doubleValue1;
    private int doubleValue2;
    /* getterとsetteerは省略 */
}

完成です。

まとめ

項目の数が決まったらParcelable.CreatorとwriteToParcelのコードに何を書くべきか自動的に決まります。しかしAndroidフレームワークはそのコードを生成はしてくれません。いちいち手で書いても良いですが、正直手間ですし、間違えると不具合の原因になります。CatHandsGendroidを使えばその間違えやすい部分を自動で生成してくれます。機械的にできるところはツールに任して、余計な不具合を出さなくて済むようにしましょう。

26
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
25