Kotlin을 사용하여 Android에서 Parcelable 데이터 클래스를 만드는 편리한 방법이 있나요?


117

저는 현재 Parcelable 클래스 생성을 용이하게하는 Java 프로젝트에서 우수한 AutoParcel 을 사용하고 있습니다.

이제 다음 프로젝트에서 고려할 Kotlin에는 equals, hashCode 및 toString 메서드를 자동으로 생성하는 이러한 데이터 클래스 개념이 있습니다.

메서드를 수동으로 구현하지 않고 편리한 방법으로 Parcelable 데이터 클래스를 Parcelable로 만드는 편리한 방법이 있습니까?


2
kapt를 시도 했습니까? blog.jetbrains.com/kotlin/2015/06/…
Sergey

Kotlin과 함께 AutoParcel을 사용 하시겠습니까? 나는 그것에 대해 생각했지만 Parcelable 데이터 클래스를 언어에 내장하는 방법이 있다면 아름답을 것입니다. 특히 Kotlin 사용의 상당 부분을 고려할 때 Android 애플리케이션에서 나옵니다.
thalesmello 2015

답변:


187

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

2
그것을 확인하고 싶은 사람들을 위해 : blog.jetbrains.com/kotlin/2017/08/kotlin-1-1-4-is-out
thalesmello

3
더 이상 데이터 클래스가 아닌 이유입니다. 이 예제는 일반적인 kotlin 클래스에 적용될 수 있음을 보여주기위한 것입니까?
Nitin Jain

10
컴파일러가 불평 this calss implements Parcelable but does not provice CREATOR field합니다. 답변이 충분합니까 (전체)?
murt

1
@murt Parcelable을 성공적으로 사용하셨습니까? CREATOR 때문에 컴파일 오류가 발생했습니다
TOP

4
@SuppressLint("ParcelCreator")보푸라기 경고를 제거 하는 데 사용할 수 있습니다 .
Dutch Masters

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

20

kotlin 데이터 클래스의 데이터 키워드를 클릭 한 다음 alt + Enter를 누르고 첫 번째 옵션을 선택하십시오. "Add Parceable Implementation"


2
이 방법을 사용했지만 몇 가지 문제가 있습니다. 때로는 대체 parcel.read...TODO필드가없는 경우 val/var. List클래스 내부에서 사용하면 구현이 문제가됩니다. 그래서 나는 @Parcelize받아 들여진 대답으로 돌아 섰다 .
CoolMind

19

PaperParcel 을 사용해 보셨습니까 ? Android Parcelable상용구 코드를 자동으로 생성하는 주석 프로세서입니다 .

용법:

생성 된 JVM 정적 인스턴스를 사용 하여 데이터 클래스에 주석을 달고 @PaperParcel구현 PaperParcelable하고 추가합니다 CREATOR. 예 :

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

이제 데이터 클래스는 Parcelable과에 직접 전달할 수있는 BundleIntent

편집 : 최신 API로 업데이트


IDE는 이제 "다른 클래스로부터의 데이터 클래스 상속이 금지됩니다"라고 말합니다. 나는 PaperParcel 데이터 클래스를 더 이상 사용할 수 없습니다 생각 ...
마시모

그들은 다른 클래스에서 상속 수 없었다 적이 있지만 인터페이스 (예를 들어 PaperParcelable) 구현할 수 있습니다
브래들리 캠벨

1
@Bradley Campbell이 줄에서 오류가 발생합니다. JvmField val CREATOR = PaperParcelExample.CREATOR는 PaperParcelExample 클래스를 만들 수 없습니다
Mr.G

16

최고의 와 방법은 없는 상용구 전혀 코드는 밀수의 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 플러그인을 사용하는 것입니다.


6

사용하여 안드로이드 스튜디오코 틀린의 플러그인을, 나는 나의 오래된 자바로 변환하는 쉬운 방법을 발견 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. 자바 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

나는 https://github.com/johncarl81/parceler lib를 사용하는 것을 선호합니다.

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

이렇게하면 'Class'MyClass 'is not abstract and does not implement abstract member public abstract fun writeToParcel (dest : Parcel !, flags : Int) : Unit defined in android.os.Parcelable
PhillyTheThrilly

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에서 Parcelization의 전체 프로세스를 쉽게 만들었습니다.

하기 위해서

1 단계. 앱 모듈 Gradle에 Kotlin 확장 프로그램 추가

2 단계. 이 기능은 여전히 ​​Gradle에서 실험 중이므로 Experiment = true를 추가합니다.

androidExtensions {실험적 = true}

3 단계. @Parcel을 사용하여 데이터 클래스 발표

다음 은 @Parcel 사용에 대한 간단한 예입니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.