我目前在Java项目中使用了出色的AutoParcel,这有助于创建Parcelable类。
现在,我在下一个项目中考虑的Kotlin具有这种数据类的概念,它可以自动生成equals,hashCode和toString方法。
有没有简便的方法可以使Kotlin数据类可打包(无需手动实现方法)?
我目前在Java项目中使用了出色的AutoParcel,这有助于创建Parcelable类。
现在,我在下一个项目中考虑的Kotlin具有这种数据类的概念,它可以自动生成equals,hashCode和toString方法。
有没有简便的方法可以使Kotlin数据类可打包(无需手动实现方法)?
Answers:
Kotlin 1.1.4已经发布
Android扩展插件现在包括一个自动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
}
}
this calss implements Parcelable but does not provice CREATOR field
。您的答案足够(完整)吗?
@SuppressLint("ParcelCreator")
用来摆脱棉绒警告。
您可以尝试以下插件:
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)
}
}
}
}
您尝试过PaperParcel吗?这是一个注释处理器,可以自动Parcelable
为您生成Android 样板代码。
用法:
使用@PaperParcel
,实现PaperParcelable
和注释您的数据类,并添加生成的JVM静态实例,CREATOR
例如:
@PaperParcel
data class Example(
val test: Int,
...
) : PaperParcelable {
companion object {
@JvmField val CREATOR = PaperParcelExample.CREATOR
}
}
现在您的数据类是Parcelable
并且可以直接传递给Bundle
或Intent
编辑:使用最新的API更新
只需点击您的kotlin数据类的data关键字,然后按alt + Enter,选择第一个选项即可 "Add Parceable Implementation"
parcel.read...
带TODO
,如果一个字段是不是val/var
。如果List
在类内部使用,则实现会成为问题。所以我转向@Parcelize
了公认的答案。
完全没有样板代码的最佳方法是Smuggler gradle插件。您只需要实现AutoParcelable接口,例如
data class Person(val name:String, val age:Int): AutoParcelable
就这样。也适用于密封类。此插件还为所有AutoParcelable类提供了编译时验证。
UPD 17.08.2017现在使用Kotlin 1.1.4和Kotlin Android扩展插件,您可以使用@Parcelize
注释。在这种情况下,上面的示例将如下所示:
@Parcelize class Person(val name:String, val age:Int): Parcelable
无需data
修饰符。目前最大的弊端是使用kotlin-android-extensions插件,该插件具有许多其他不必要的功能。
使用Android Studio和Kotlin插件,我发现了一种无需额外插件即可转换旧Java Parcelable
的简便方法(如果您只想将全新的类转换为,请跳至第4个代码段)。 data
Parcelable
假设您有一个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
类定义中。
笔记:
Parcelable
直接转换为Kotlin不会与当前版本的Java产生相同的结果 Kotlin插件(1.1.3
)。Parcelable
代码生成器引入的。必须是一个小错误。希望本技巧对您同样有用。
我将离开我的工作方式,以防它可能对某人有所帮助。
我要做的是我有一个通用的 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()) } }
}
这使我摆脱了样板重写。
范例:
@Parcelize
data class Item(
var imageUrl: String,
var title: String,
var description: Category
) : Parcelable
不幸的是,在Kotlin中无法将真实字段放入接口中,因此您不能免费从interface-adapter继承它:
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)
您可以使用@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
块。
有一个插件,但并不总是随着Kotlin的发展而更新:https : //plugins.jetbrains.com/plugin/8086
替代方案:
我有一个使用Parcelable
和列表的自定义数据类的工作示例:
结合列表使用Parcelable的数据类:
希望能帮助到你!