Использование Parceler с классом данных Kotlin с конструктором для сериализации
Есть ли способ использовать Parceler с классами данных и конструктором данных Kotlin для сериализации без использования аннотации @ParcelProperty
для каждого поля?
Если я попытаюсь использовать библиотеку следующим образом:
@Parcel
data class Valve @ParcelConstructor constructor(val size: Int)
Я получаю Error:Parceler: No corresponding property found for constructor parameter arg0
. Но если я добавлю @ParcelProperty("size")
, то все будет отлично.
Почему это?
Обновление:
Есть и другой способ использования этой библиотеки.
Я мог бы просто удалить аннотацию @ParcelConstructor
, но тогда я получу ошибку
Error:Parceler: No @ParcelConstructor annotated constructor and no default empty bean constructor found.
Я думаю (не проверял его), я также мог бы сделать все параметры конструктора необязательными и добавить @JvmOverloads
, но у меня есть побочный эффект, который я должен проверить на все свойства класса, если они являются нулевыми или нет.
Обновление 2:
Это то, что сработало для меня:
@Parcel
data class Valve(val size: Int? = null)
В коротком сгенерированном классе Java должен быть пустой конструктор по умолчанию. Один из способов добиться этого - сделать так, как указано выше - все переменные должны иметь значения по умолчанию.
Ответы
Ответ 1
В соответствии с документами Parceler по умолчанию работает с общедоступными полями. Но обычный Kotlin data class
(как в вашем примере) скорее является "традиционным getter/setter bean", так как каждое свойство Kotlin представлено частным полем и getter/[setter].
TL; ДР: Я думаю, что это сработает:
@Parcel(Serialization.BEAN)
data class Valve(val size: Int = 10)
Обратите внимание на значение по умолчанию, оно позволяет Kotlin автоматически генерировать дополнительный пустой конструктор, который требуется спецификацией Java Been.
Другим способом было бы отметить конструктор, который у нас уже есть:
@Parcel(Serialization.BEAN)
data class Driver @ParcelConstructor constructor(val name: String)
Конкретный документ: https://github.com/johncarl81/parceler#gettersetter-serialization
Ответ 2
Я знаю, что на этот вопрос уже есть ответ, но для будущих зрителей, которые также пытаются заставить Parceler работать с объектами данных kotlin, я написал новый процессор аннотаций, чтобы сгенерировать шаблон Parcelable для классов данных Kotlin. Он предназначен для значительного сокращения стандартного кода при создании классов данных Parcelable:
https://github.com/grandstaish/paperparcel
Использование:
Аннотируйте свой класс данных с помощью @PaperParcel
, реализуйте PaperParcelable
и добавьте статический экземпляр JVM сгенерированного CREATOR
например:
@PaperParcel
data class Example(
val test: Int,
...
) : PaperParcelable {
companion object {
@JvmField val CREATOR = PaperParcelExample.CREATOR
}
}
Теперь ваш класс данных Parcelable
и может быть передан непосредственно в Bundle
или Intent
Изменить: обновить с последним API
Ответ 3
Просто добавьте конструктор по умолчанию:
@Parcel
data class Valve(val size: Int) {
constructor() : this(0)
}
Ответ 4
если вы используете kotlin 1.1.4 или выше, очень просто использовать аннотацию @Parcelize
Для этого сначала добавьте это в build.gradle
android {
//other codes
//for using latest experimental build of Android Extensions
androidExtensions {
experimental = true
}
}
Тогда ваш класс должен понравиться
@Parcelize
data class Valve(val size: Int? = null) : Parcelable