有没有一种方便的方法在Android中使用Kotlin创建Parcelable数据类?

时间:2015-11-05 18:19:31

标签: android parcelable kotlin

我目前正在Java项目中使用优秀的AutoParcel,这有助于创建Parcelable类。

现在,我考虑用于下一个项目的Kotlin具有这种数据类概念,可以自动生成equals,hashCode和toString方法。

是否有方便的方法以便捷的方式制作Kotlin数据类Parcelable(不手动实现方法)?

15 个答案:

答案 0 :(得分:145)

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

答案 1 :(得分:45)

你可以尝试这个插件:

<强> android-parcelable-intellij-plugin-kotlin

它可以帮助您为kotlin的数据类生成Android Parcelable样板代码。它最终看起来像这样:

[Codes to show progressDialog]

Ion.with(MainActivity.this)
            .load("--URL TO POST JSON DATA--")
            .setJsonObjectBody(params[0])
            .asJsonObject()
            .withResponse()
            .setCallback(new FutureCallback<Response<JsonObject>>() 
{
                @Override
                public void onCompleted(Exception e, Response<JsonObject> result) {
if(progressDialog.isShowing()){

        progressDialog.dismiss();

        //TODO Something

    }
                    if (result != null) {
                        if (result.getHeaders().code() == 200) {

                            Toast.makeText(MainActivity.this, "Login Success", Toast.LENGTH_SHORT).show();

                        } else if (result.getHeaders().code() == 401) {
                            Toast.makeText(MainActivity.this, "Invalid Username or password", Toast.LENGTH_LONG).show();

                        } else {
                            Toast.makeText(MainActivity.this, "Something wrong check connection !!!", Toast.LENGTH_SHORT).show();
                        }
                    }
                }
            });

答案 2 :(得分:19)

你试过PaperParcel吗?它是一个注释处理器,可以自动生成Android Parcelable样板代码。

<强>用法:

使用@PaperParcel注释您的数据类,实现PaperParcelable,并添加生成的CREATOR的JVM静态实例,例如:

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

现在您的数据类为Parcelable,可以直接传递给BundleIntent

修改:使用最新的API进行更新

答案 3 :(得分:15)

使用无样板代码的最佳方式是Smuggler gradle插件。您只需要实现AutoParcelable接口,如

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

这就是全部。适用于密封课程。此插件还为所有AutoParcelable类提供编译时验证。

UPD 17.08.2017 现在使用Kotlin 1.1.4 and Kotlin Android extensions plugin,您可以使用@Parcelize注释。在这种情况下,上面的示例将如下所示:

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

无需data修饰符。目前最大的缺点是使用kotlin-android-extensions插件,它有许多其他功能,可能是不必要的。

答案 4 :(得分:14)

只需点击你的kotlin数据类的data关键字,然后按alt + Enter,选择第一个选项"Add Parceable Implementation"

答案 5 :(得分:4)

我会离开我的路,以防它可以帮助某人。

我所做的是我有一个通用After gtkThread declaration 5 4 3 2 1

<LinearLayout
        android:id="@+id/tabs_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_alignParentBottom="true">

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="2dp"
            android:orientation="vertical"
            android:background="@color/lfp_yellow"/>

        <com.astuetz.PagerSlidingTabStrip
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="48dip"
            app:pstsDividerColor="@android:color/transparent"
            app:pstsIndicatorColor="@color/light_yellow"
            app:pstsIndicatorHeight="4px"
            app:pstsShouldExpand="true"/>
    </LinearLayout>

然后我创建这样的parcelables:

Parcelable

这让我摆脱了样板覆盖。

答案 6 :(得分:4)

使用 Android Studio Kotlin 插件,我找到了一种简单的方法来转换我的旧Java Parcelable,其中没有额外的插件(如果您想要将全新的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 对象(属性应该是最终的并由构造函数设置):

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 Parcelable直接转换为 Kotlin ,与当前版本的 Kotlin 不会产生相同的结果插件(1.1.3)。
  2. 我不得不删除当前Parcelable代码生成器引入的一些额外花括号。必须是一个小错误。
  3. 我希望这个提示对你有效,对我来说也是如此。

答案 7 :(得分:4)

您可以使用@Parcelize注释来做到这一点。这是一个自动的Parcelable实现生成器。

首先,您需要允许他们将其添加到模块的build.gradle:

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

在主构造函数中声明序列化的属性,并添加一个@Parcelize批注,然后将自动创建writeToParcel() / createFromParcel()方法:

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

不要需要在experimental = true块内添加androidExtensions

答案 8 :(得分:3)

不幸的是,Kotlin无法在界面中放置真实字段,因此您无法从接口适配器免费继承它: data class Par : MyParcelable

您可以查看代表团,但它对字段没有帮助,AFAIK:https://kotlinlang.org/docs/reference/delegation.html

所以我看到的唯一选项是Parcelable.Creator的结构函数,这很明显。

答案 9 :(得分:2)

我更喜欢使用https://github.com/johncarl81/parceler lib和

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

答案 10 :(得分:0)

有一个插件,但并不总是像Kotlin正在发展的那样更新: https://plugins.jetbrains.com/plugin/8086

<强>替代: 我有一个使用atp install nodejs的自定义数据类的工作示例,并列出:

使用带列表的Parcelable的数据类:

  

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

希望它有所帮助!

答案 11 :(得分:0)

Kotlin的@Parcel批注使Android该死的整个打包过程变得容易。

要这样做

第1步。在应用模块gradle中添加Kotlin扩展

第2步。添加experimental = true,因为此功能仍在gradle中进行实验。

  

androidExtensions {       实验=真   }

第3步。使用@Parcel取消数据类

Here 是有关@Parcel使用情况的简单示例

答案 12 :(得分:0)

  • 在模型/数据类的顶部使用 @Parcelize 批注
  • 使用Kotlin的最新版本
  • 在您的应用模块中使用最新版本的Kotlin Android扩展

示例:

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

答案 13 :(得分:0)

以下Kotlin代码可以帮助您使用父级和子级数据类创建Parcelable数据类

父数据类-MyPostModel

data class MyPostModel(
    @SerializedName("post_id") val post_id: String? = "",
    @SerializedName("category_id") val category_id: String? = "",
    @SerializedName("images") val images: ArrayList<ImagesModel>? = null
) : Parcelable {
    constructor(parcel: Parcel) : this(
        parcel.readString(),
        parcel.readString(),
        parcel.createTypedArrayList(ImagesModel.CREATOR)
    )

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(post_id)
        parcel.writeString(category_id)
        parcel.writeTypedList(images)
    }

    override fun describeContents(): Int {
        return 0
    }

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

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

子数据类-ImagesModel

data class ImagesModel(
    @SerializedName("image_id") val image_id: String? = "",
    @SerializedName("image_url") val image_url: String? = ""
) : Parcelable {
    constructor(parcel: Parcel) : this(
        parcel.readString(),
        parcel.readString()
    )

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(image_id)
        parcel.writeString(image_url)
    }

    override fun describeContents(): Int {
        return 0
    }

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

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

答案 14 :(得分:0)

一种更简单,最新的方法是使用@Parcelize批注,该批注消除了实现Parcelable的繁琐工作

build.gradle(应用程序模块)

apply plugin: "kotlin-parcelize"

// If you are using the new plugin format use this instead.
plugins{
    ...
    id "kotlin-parcelize"
}

YourClass.kt

import kotlinx.parcelize

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