Kotlinを使用してAndroidでParcelableデータクラスを作成する便利な方法はありますか?


116

現在、Javaプロジェクトで優れたAutoParcelを使用しています。これにより、Parcelableクラスの作成が容易になります。

現在、次のプロジェクトで検討するKotlinには、equals、hashCode、およびtoStringメソッドを自動的に生成するデータクラスの概念があります。

(メソッドを手動で実装せずに)Kotlinデータクラスを便利な方法でParcelableにする便利な方法はありますか?


2
kaptを試しましたか? blog.jetbrains.com/kotlin/2015/06/…–
セルゲイ

AutoParcelをKotlinで使用するつもりですか?私はそれについて考えましたが、Parcelableのデータクラスを言語に組み込む方法があれば、それは素晴らしいことです。特にKotlinの使用の大部分がAndroidアプリケーションに由来することを考慮してください。
thalesmello 2015年

回答:


187

Kotlin 1.1.4リリースされました

Android Extensionsプラグインに、自動Parcelable実装ジェネレータが含まれるようになりました。プライマリコンストラクターでシリアル化されたプロパティを宣言し、@ Parcelizeアノテーションを追加すると、writeToParcel()/ createFromParcel()メソッドが自動的に作成されます。

@Parcelize
class User(val firstName: String, val lastName: String) : Parcelable

そのため、モジュールのbuild.gradleにこれを追加できるようにする必要があります。

apply plugin: 'org.jetbrains.kotlin.android.extensions'

android {
    androidExtensions {
        experimental = true
    }
}

2
チェックしたい人のために:blog.jetbrains.com/kotlin/2017/08/kotlin-1-1-4-is-out
thalesmello

3
なぜこれはもはやデータクラスではないのですか?この例は、これが任意の汎用kotlinクラスに適用できることを示すためだけのものですか?
Nitin Jain 2017

10
コンパイラは文句を言うthis calss implements Parcelable but does not provice CREATOR field。あなたの答えは十分(十分)ですか?
MURT

1
@murt Parcelableを正常に使用しましたか?CREATORが原因でコンパイルエラーが発生しました
TOP

4
@SuppressLint("ParcelCreator")lint警告を取り除くために使用できます。
ダッチマスターズ

47

このプラグインを試すことができます:

android-parcelable-intellij-plugin-kotlin

KotlinのデータクラスのAndroid Parcelableボイラープレートコードを生成するのに役立ちます。そして、最終的には次のようになります。

data class Model(var test1: Int, var test2: Int): Parcelable {

    constructor(source: Parcel): this(source.readInt(), source.readInt())

    override fun describeContents(): Int {
        return 0
    }

    override fun writeToParcel(dest: Parcel?, flags: Int) {
        dest?.writeInt(this.test1)
        dest?.writeInt(this.test2)
    }

    companion object {
        @JvmField final val CREATOR: Parcelable.Creator<Model> = object : Parcelable.Creator<Model> {
            override fun createFromParcel(source: Parcel): Model{
                return Model(source)
            }

            override fun newArray(size: Int): Array<Model?> {
                return arrayOfNulls(size)
            }
        }
    }
}

19

PaperParcelを試しましたか?これは、Android Parcelableボイラープレートコードを自動的に生成するアノテーションプロセッサです。

使用法:

でデータクラスに注釈を付け@PaperParcel、実装しPaperParcelable、生成されたJVM静的インスタンスを追加します。CREATOR例:

@PaperParcel
data class Example(
  val test: Int,
  ...
) : PaperParcelable {
  companion object {
    @JvmField val CREATOR = PaperParcelExample.CREATOR
  }
}

これで、データクラスはまたはにParcelable直接渡すことができます。BundleIntent

編集:最新のAPIで更新


IDEでは、「他のクラスからのデータクラスの継承は禁止されています」と表示されます。PaperParcelはデータクラスでもう使用できないと思います...
Massimo

彼らは、他のクラスから継承することができなかったんが、彼らはインタフェース(例えばPaperParcelable)を実装することができます
ブラッドリー・キャンベル

1
@Bradley Campbellこれにより、この行にエラーが表示されますJvmField val CREATOR = PaperParcelExample.CREATORはPaperParcelExampleクラスを作成できません
Mr.G

19

kotlinデータクラスのdataキーワードをクリックして、Alt + Enterキーを押し、最初のオプションを選択してください "Add Parceable Implementation"


2
この方法を使用しましたが、いくつかの問題があります。時にはそれは代用parcel.read...TODOフィールドがない場合は、val/varListクラス内で使用すると、実装が問題になります。だから私@Parcelizeは受け入れられた答えに頼った。
CoolMind

16

最善との双方向無定型のすべてのコードがあるスマグラーのGradleプラグイン。必要なのは、AutoParcelableインターフェイスを実装するだけです。

data class Person(val name:String, val age:Int): AutoParcelable

そして、それだけです。密封されたクラスでも動作します。また、このプラグインは、すべてのAutoParcelableクラスのコンパイル時検証を提供します。

UPD 2017年8月17日で今Kotlin 1.1.4とKotlin Androidの拡張プラグインあなたが使用できる@Parcelize注釈を。この場合、上記の例は次のようになります。

@Parcelize class Person(val name:String, val age:Int): Parcelable

data修飾子は必要ありません。今のところ最大の欠点は、不要になる可能性のある他の多くの機能を備えたkotlin-android-extensionsプラグインを使用していることです。


6

Android StudioKotlinプラグインを使用Parcelableして、余分なプラグインなしで古いJavaを簡単に変換する方法を見つけました(まったく新しいdataクラスをにしたい場合はParcelable、4番目のコードスニペットにスキップします)。

PersonすべてのParcelableボイラープレートを含むクラスがあるとします。

public class Person implements Parcelable{
    public static final Creator<Person> CREATOR = new Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel in) {
            return new Person(in);
        }

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

    private final String firstName;
    private final String lastName;
    private final int age;

    public Person(String firstName, String lastName, int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    protected Person(Parcel in) {
        firstName = in.readString();
        lastName = in.readString();
        age = in.readInt();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(firstName);
        dest.writeString(lastName);
        dest.writeInt(age);
    }

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

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public int getAge() {
        return age;
    }
}

まず、Parcelable実装を削除して、必要最小限のプレーンな古いJavaオブジェクトを残します(プロパティはfinalであり、コンストラクターによって設定される必要があります)。

public class Person {
    private final String firstName;
    private final String lastName;
    private final int age;

    public Person(String firstName, String lastName, int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public int getAge() {
        return age;
    }
}

次に、Code > Convert Java file to Kotlin Fileオプションにその魔法をさせましょう:

class Person(val firstName: String, val lastName: String, val age: Int)

これをdataクラスに変換します。

data class Person(val firstName: String, val lastName: String, val age: Int)

そして最後に、これをParcelableもう一度変えましょう。クラス名にカーソルを合わせると、Android Studioでにオプションが表示されAdd Parcelable Implementationます。結果は次のようになります。

data class Person(val firstName: String, val lastName: String, val age: Int) : Parcelable {
    constructor(parcel: Parcel) : this(
            parcel.readString(),
            parcel.readString(),
            parcel.readInt()
    )

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(firstName)
        parcel.writeString(lastName)
        parcel.writeInt(age)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<Person> {
        override fun createFromParcel(parcel: Parcel): Person {
            return Person(parcel)
        }

        override fun newArray(size: Int): Array<Person?> {
            return arrayOfNulls(size)
        }
    }
}

ご覧のとおり、Parcelable実装はdataクラス定義に追加された自動生成コードです。

ノート:

  1. Java ParcelableKotlinに直接変換しようとしても、現在のバージョンのKotlinプラグイン(1.1.3では同じ結果が得られません。
  2. 現在のParcelableコードジェネレーターで導入されている余分な中かっこをいくつか削除する必要がありました。マイナーなバグでなければなりません。

このヒントがあなたにとっても私にとってもうまくいくことを願っています。


4

それが誰かを助けるかもしれない場合のために私は自分のやり方を残します。

私は何をしているのですか Parcelable

interface DefaultParcelable : Parcelable {
    override fun describeContents(): Int = 0

    companion object {
        fun <T> generateCreator(create: (source: Parcel) -> T): Parcelable.Creator<T> = object: Parcelable.Creator<T> {
            override fun createFromParcel(source: Parcel): T = create(source)

            override fun newArray(size: Int): Array<out T>? = newArray(size)
        }

    }
}

inline fun <reified T> Parcel.read(): T = readValue(T::class.javaClass.classLoader) as T
fun Parcel.write(vararg values: Any?) = values.forEach { writeValue(it) }

そして、私はこのような小包を作成します:

data class MyParcelable(val data1: Data1, val data2: Data2) : DefaultParcelable {
    override fun writeToParcel(dest: Parcel, flags: Int) { dest.write(data1, data2) }
    companion object { @JvmField final val CREATOR = DefaultParcelable.generateCreator { MyParcelable(it.read(), it.read()) } }
}

これにより、ボイラープレートオーバーライドを取り除くことができます。


4
  • モデル/データクラスの上部で@Parcelizeアノテーションを使用する
  • Kotlinの最新バージョンを使用する
  • アプリモジュールでKotlin Android拡張機能の最新バージョンを使用する

例:

@Parcelize
data class Item(
    var imageUrl: String,
    var title: String,
    var description: Category
) : Parcelable

3

残念ながら、Kotlinではインターフェイスに実際のフィールドを配置する方法がないため、インターフェイスアダプターからフィールドを無料で継承することはできません。 data class Par : MyParcelable

あなたは委任を見るかもしれませんが、それはフィールドを助けません、AFAIK:https ://kotlinlang.org/docs/reference/delegation.html

したがって、私が見る唯一のオプションは、のファブリック関数ですParcelable.Creator



2

@Parcelizeアノテーションを使用してそれを行うことができます。これは自動Parcelable実装ジェネレーターです。

まず、これを有効にして、これをモジュールのbuild.gradleに追加する必要があります。

apply plugin: 'org.jetbrains.kotlin.android.extensions'

プライマリコンストラクターでシリアル化されたプロパティを宣言し、@Parcelize注釈を追加すると、writeToParcel()/ createFromParcel()メソッドが自動的に作成されます。

@Parcelize
class User(val firstName: String, val lastName: String) : Parcelable

あなたDONTの追加の必要性experimental = true内部androidExtensionsブロックを。


1

Kotlinは、@ Parcelアノテーションを使用して、Androidでのパーセル化のプロセス全体を非常に簡単にしています。

そうするために

ステップ1.アプリモジュールGradleにKotlin拡張機能を追加する

ステップ2.この機能はまだgradleで実験中なので、experimental = trueを追加します。

androidExtensions {experimental = true}

ステップ3. @Parcelでデータクラスに注釈を付ける

ここで @Parcel使用に関する簡単な例です


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.