Kotlin을 사용하여 Android에서 Parcelable 데이터 클래스를 만드는 편리한 방법이 있나요?
현재 Java 프로젝트에서 Parcelable 클래스 생성을 용이하게하는 뛰어난 AutoParcel 을 사용하고 있습니다.
이제 다음 프로젝트에서 고려할 Kotlin에는 equals, hashCode 및 toString 메소드를 자동으로 생성하는 데이터 클래스 개념이 있습니다.
메서드를 수동으로 구현하지 않고 편리한 방식으로 Parcelable 데이터 클래스를 Parcelable로 만드는 편리한 방법이 있습니까?
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
}
}
이 플러그인을 사용해 볼 수 있습니다.
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 을 사용해 보셨습니까 ? Android Parcelable
상용구 코드를 자동으로 생성하는 주석 프로세서입니다 .
용법:
생성 된 JVM 정적 인스턴스를 사용 하여 데이터 클래스에 주석을 달고 @PaperParcel
구현 PaperParcelable
하고 추가합니다 CREATOR
. 예 :
@PaperParcel
data class Example(
val test: Int,
...
) : PaperParcelable {
companion object {
@JvmField val CREATOR = PaperParcelExample.CREATOR
}
}
이제 데이터 클래스는 Parcelable
과에 직접 전달할 수있는 Bundle
나Intent
편집 : 최신 API로 업데이트
kotlin 데이터 클래스의 데이터 키워드를 클릭 한 다음 alt + Enter를 누르고 첫 번째 옵션을 선택하십시오. "Add Parceable Implementation"
최고의 와 방법은 없는 상용구 전혀 코드는 밀수의 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 플러그인을 사용하는 것입니다.
누군가에게 도움이 될 경우를 대비하여 내 방식을 떠날 것입니다.
내가하는 일은 제네릭이 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()) } }
}
Which gets me rid of that boilerplate override.
Using Android Studio and the Kotlin plugin, I found an easy way to convert my old Java Parcelable
s with no extra plugins (if all you want is to turn a brand new data
class into a Parcelable
, skip to the 4th code snippet).
Let's say you have a Person
class with all the Parcelable
boiler plate:
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;
}
}
Start by stripping out the Parcelable
implementation, leaving a bare-bones, plain, old Java object (properties should be final and set by the constructor):
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;
}
}
Then let the Code > Convert Java file to Kotlin File
option do its magic:
class Person(val firstName: String, val lastName: String, val age: Int)
Convert this into a data
class:
data class Person(val firstName: String, val lastName: String, val age: Int)
And finally, let's turn this into a Parcelable
again. Hover the class name and Android Studio should give you the option to Add Parcelable Implementation
. The result should look like this:
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)
}
}
}
As you can see, the Parcelable
implementation is some auto-generated code appended to you data
class definition.
Notes:
- Trying to convert a Java
Parcelable
directly into Kotlin will not produce the same result with the current version of the Kotlin plugin (1.1.3
). - I had to remove some extra curly braces the current
Parcelable
code generator introduces. Must be a minor bug.
I hope this tip works for you as well as it did for me.
Unfortunately there is no way in Kotlin to put a real field in an interface, so you can't inherit it from an interface-adapter for free: data class Par : MyParcelable
You may look at delegation, but it does not help with fields, AFAIK: https://kotlinlang.org/docs/reference/delegation.html
So the the only option I see is a fabric function for Parcelable.Creator
, which is kind of obvious.
i prefer just using the https://github.com/johncarl81/parceler lib with
@Parcel(Parcel.Serialization.BEAN)
data class MyClass(val value)
- Use @Parcelize annotation on top of your Model / Data class
- Use latest version of Kotlin
- Use latest version of Kotlin Android Extensions in your app module
Example :
@Parcelize
data class Item(
var imageUrl: String,
var title: String,
var description: Category
) : Parcelable
There is a Plugin but is not always as updated as Kotlin is evolving: https://plugins.jetbrains.com/plugin/8086
Alternative: I have a working example of a custom data class using Parcelable
and lists:
Data classes using Parcelable with Lists:
Hope it helps!
Kotlin has made the entire process of Parcelization in Android damn easy with its @Parcel annotation.
To do that
Step 1. Add Kotlin extensions in your app module gradle
Step 2. Add experimental = true since this feature is still in experimentation in gradle.
androidExtensions { experimental = true }
Step 3. Annonate the data class with @Parcel
Here is an simple example on @Parcel usage
'developer tip' 카테고리의 다른 글
PHP를 사용하여 JSON 파일에서 데이터 가져 오기 (0) | 2020.08.17 |
---|---|
파이썬 셸에서 pyspark 가져 오기 (0) | 2020.08.17 |
Powershell에서 "@"기호는 무엇을합니까? (0) | 2020.08.17 |
SSH를 로그 아웃 한 후에도 백그라운드에서 Python 스크립트를 실행하는 방법은 무엇입니까? (0) | 2020.08.17 |
히스토그램 Matplotlib (0) | 2020.08.17 |