Есть ли удобный способ создания классов данных Parcelable в Android с помощью Kotlin?



в настоящее время я использую отличный AutoParcel в моем проекте Java, который облегчает создание Parcelable классов.



теперь Kotlin, который я рассматриваю для своего следующего проекта, имеет эту концепцию классов данных, которые автоматически генерируют методы equals, hashCode и toString.



есть ли удобный способ сделать класс данных Kotlin Parcelable удобным способом (без реализации методов вручную)?

946   12  

12 ответов:

Котлин 1.1.4 выходит

Android расширения плагин теперь включает в себя автоматический генератор Parcelable реализации. Объявите сериализованные свойства в основном конструкторе и добавьте аннотацию @Parcelize, а методы writeToParcel()/createFromParcel () будут созданы автоматически:

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

поэтому вам нужно включить их добавление этого к вам модуля построить.gradle:

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

android {
    androidExtensions {
        experimental = true
    }
}

вы можете попробовать этот плагин:

android-parcelable-intellij-plugin-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)
            }
        }
    }
}

вы пробовали PaperParcel? Это процессор аннотаций, который автоматически генерирует Android Parcelable шаблонный код для вас.

использование:

аннотировать класс данных с помощью @PaperParcel реализовать PaperParcelable, и добавить статический экземпляр JVM сгенерированного CREATOR например:

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

теперь ваш класс данных Parcelable и может быть передан непосредственно к Bundle или Intent

Edit: Обновление с последним API

The лучшие С нет шаблонного код на все контрабандист gradle плагин. Все, что вам нужно, это просто реализовать AutoParcelable интерфейс, как

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

и это все. Работает и для закрытых классов. Также Этот плагин обеспечивает проверку времени компиляции для всех классов AutoParcelable.

UPD 17.08.2017 теперь Котлин Котлин и 1.1.4 для Android расширений плагинов вы могли бы использовать @Parcelize Примечание. В этом случае приведенный выше пример будет выглядеть так:

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

не нужно data модификатор. Самым большим недостатком на данный момент является использование плагина kotlin-android-extensions, который имеет множество других функций, которые могут быть ненужными.

просто нажмите на ключевое слово данных вашего класса данных kotlin, затем нажмите alt + Enter, выберите первый вариант, сказав "Add Parceable Implementation"

Я оставлю мой способ делать в случае, если это может помочь кому-то.

то, что я делаю, это у меня есть общий 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) }

и затем я создаю parcelables, как это:

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()) } }
}

что избавляет меня от этого шаблонного переопределения.

к сожалению, в Kotlin нет способа поместить реальное поле в интерфейс, поэтому вы не можете наследовать его от интерфейса-адаптера бесплатно: data class Par : MyParcelable

вы можете посмотреть делегирование, но это не помогает с полями, AFAIK:https://kotlinlang.org/docs/reference/delegation.html

Так что единственный вариант, который я вижу, это функция fabric для Parcelable.Creator, что является очевидным.

Я предпочитаю просто использовать https://github.com/johncarl81/parceler lib с

@Parcel(Parcel.Serialization.BEAN)
data class MyClass(val value)

используя Android Studio и Котлин плагин, я нашел простой способ конвертировать мой старый Java ParcelableС никаких дополнительных плагинов (если все, что вы хотите превратить Новый data класс В a 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 объект (свойства должны быть окончательными и заданы конструктором):

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. преобразование JavaParcelable непосредственно в Котлин не будет производить тот же результат с текущей версией Котлин плагин (1.1.3).
  2. мне пришлось удалить некоторые дополнительные фигурные скобки текущий Parcelable генератор код вводит. Должно быть, небольшая ошибка.

я надеюсь, что этот совет работает для вас, а также для меня.

есть плагин, но не всегда обновляется, как Котлин развивается: https://plugins.jetbrains.com/plugin/8086

альтернатива: У меня есть рабочий пример пользовательского класса данных с помощью Parcelable и списки:

классы данных, использующие Parcelable со списками:

https://gist.github.com/juanchosaravia/0b61204551d4ec815bbf

надеюсь, что это помогает!

Котлин сделал весь процесс Parcelization в Android чертовски легко с его @ Parcel аннотации.

для этого

Шаг 1. добавьте расширения Kotlin в свой модуль приложения gradle

Шаг 2. добавить экспериментальный = true, так как эта функция все еще находится в эксперименте в gradle.

androidExtensions { экспериментальный = истинный }

Шаг 3. Annonate класс данных с @участков

здесь это простой пример использования @ Parcel

Котлин сделал весь процесс Parcelization в Android чертовски легко с его @ Parcel аннотации.

для этого

Шаг 1. добавьте расширения Kotlin в свой модуль приложения gradle

Шаг 2. добавить экспериментальный = true, так как эта функция все еще находится в эксперименте в gradle.

androidExtensions { экспериментальный = истинный }

Шаг 3. Annonate класс данных с @участков

здесь это простой пример использования @Parcel в Kotlin для передачи данных между компонентами Android.

Comments

    Ничего не найдено.