क्या कोटलिन के साथ एंड्रॉइड में पार्सलेबल डेटा कक्षाएं बनाने का एक सुविधाजनक तरीका है?


117

मैं वर्तमान में अपने जावा प्रोजेक्ट में उत्कृष्ट ऑटोपारसेल का उपयोग कर रहा हूं , जो पार्सलेबल कक्षाओं के निर्माण की सुविधा प्रदान करता है।

अब, कोटलिन, जिसे मैं अपनी अगली परियोजना के लिए विचार करता हूं, में डेटा वर्गों की यह अवधारणा है, जो स्वचालित रूप से बराबरी, हैशकोड औरString तरीकों को उत्पन्न करता है।

क्या कोटलिन डेटा वर्ग को एक सुविधाजनक तरीके से पार्सल करने का एक सुविधाजनक तरीका है (मैन्युअल तरीके लागू किए बिना)?


2
क्या आपने कप्ट की कोशिश की? blog.jetbrains.com/kotlin/2015/06/…
सर्गेई

आप कोटलीन के साथ AutoParcel का उपयोग करने का मतलब है? मैंने इसके बारे में सोचा था, लेकिन अगर वहाँ डेटा वर्गों Parcelable भाषा में बनाया गया था, यह सुंदर होगा। विशेष रूप से कोटलिन के उपयोग का एक बड़ा हिस्सा एंड्रॉइड अनुप्रयोगों से आएगा।
थेल्समेलो 21

जवाबों:


187

कोटलिन 1.1.4 आउट हैं

एंड्रॉइड एक्सटेंशन्स प्लगइन में अब एक स्वचालित पार्सलेबल कार्यान्वयन जनरेटर शामिल है। एक प्राथमिक निर्माता में क्रमबद्ध गुणों की घोषणा करें और एक @Parcelize एनोटेशन जोड़ें, और writeToParcel () / createFromParcel () विधियाँ स्वचालित रूप से बनाई जाएंगी:

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

इसलिए आपको उन्हें मॉड्यूल के बिल्ड.ग्रेड में जोड़ने में सक्षम करने की आवश्यकता है :

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
यह अब डेटा क्लास क्यों नहीं है। क्या यह उदाहरण केवल यह दिखाने के लिए है कि यह किसी भी सामान्य कोटलिन वर्ग पर लागू किया जा सकता है?
नितिन जैन

10
संकलक शिकायत करता है this calss implements Parcelable but does not provice CREATOR field। क्या आपका उत्तर पर्याप्त (पूर्ण) है?
murt

1
@ क्या आपने पार्सलबल का सफलतापूर्वक उपयोग किया है? मैं कंस्ट्रक्टर के कारण संकलित त्रुटि का सामना कर रहा हूँ
टॉप

4
आप @SuppressLint("ParcelCreator")लिंट चेतावनी से छुटकारा पाने के लिए उपयोग कर सकते हैं ।
डच मास्टर्स

47

आप इस प्लगइन की कोशिश कर सकते हैं:

android-parcelable-IntelliJ-प्लगइन-kotlin

यह आपको कोटलिन के डेटा वर्ग के लिए एंड्रॉइड पार्सलेबल बॉयलरप्लेट कोड उत्पन्न करने में मदद करता है। और यह अंत में इस तरह दिखता है:

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

बस अपने कोटलिन डेटा वर्ग के डेटा कीवर्ड पर क्लिक करें, फिर alt + Enter दबाएं, पहले विकल्प का चयन करें "Add Parceable Implementation"


2
मैंने इस पद्धति का उपयोग किया, लेकिन इसमें कई समस्याएं हैं। कभी-कभी यह एक के parcel.read...साथ स्थानापन्न करता है TODO, यदि कोई फ़ील्ड नहीं है val/var। यदि आप Listएक वर्ग के अंदर उपयोग करते हैं , तो आपका कार्यान्वयन एक समस्या बन जाता है। इसलिए मैं @Parcelizeस्वीकृत उत्तर में बदल गया ।
कूलमैन्ड

19

क्या आपने पेपरपर्ल की कोशिश की है ? यह एक एनोटेशन प्रोसेसर है जो स्वचालित रूप से आपके लिए एंड्रॉइड Parcelableबॉयलरप्लेट कोड उत्पन्न करता है ।

उपयोग:

अपने डेटा वर्ग को एनोटेट करें @PaperParcel, कार्यान्वित करें PaperParcelable, और उत्पन्न जेवीएम स्थिर उदाहरण में जोड़ें CREATOR:

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

अब आपका डेटा वर्ग है Parcelableऔर इसे सीधे Bundleया तो पास किया जा सकता हैIntent

संपादित करें: नवीनतम एपीआई के साथ अद्यतन करें


अब IDE कहता है "अन्य वर्गों से डेटा श्रेणी की विरासत निषिद्ध है"। मुझे लगता है कि PaperParcel का उपयोग अब डेटा वर्गों के साथ नहीं किया जा सकता है ...
मैसिमो

वे कभी भी अन्य वर्गों से विरासत में नहीं मिले, लेकिन वे इंटरफेस को लागू कर सकते हैं (जैसे पेपरपर्सेबल)
ब्रैडली कैंपबेल

1
@ ब्रैडली कैंपबेल मुझे इस लाइन में एक त्रुटि देता है JvmField val CREATOR = PaperParcelExample.CREATOR, पेपरपर्ल एक्सप्लोरेशन क्लास नहीं बना सकता
Mr.G

16

सबसे अच्छा के साथ जिस तरह से कोई बॉयलरप्लेट बिल्कुल कोड है तस्कर Gradle प्लगइन। बस आपको जरूरत है जैसे AutoParcelable इंटरफ़ेस को लागू करने की

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

और बस यही। सीलबंद कक्षाओं के लिए भी काम करता है। इसके अलावा यह प्लगइन सभी ऑटोपरेसेबल कक्षाओं के लिए संकलन समय सत्यापन प्रदान करता है।

UPD 17.08.2017 अब Kotlin 1.1.4 और Kotlin Android एक्सटेंशन प्लगइन के साथ आप @Parcelizeएनोटेशन का उपयोग कर सकते हैं । इस मामले में, ऊपर का उदाहरण दिखेगा:

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

dataसंशोधक की कोई आवश्यकता नहीं । सबसे बड़ा नकारात्मक पहलू यह है कि अब कोटलिन-एंड्रॉइड-एक्सटेंशन प्लगइन का उपयोग कर रहा है जिसमें बहुत सारे अन्य कार्य हैं जो अनावश्यक हो सकते हैं।


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कार्यान्वयन , नंगे-हड्डियों, सादे, पुराने जावा ऑब्जेक्ट को छोड़ दें (गुण अंतिम होना चाहिए और निर्माता द्वारा निर्धारित किया जाना चाहिए):

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. कोटलिन में सीधे जावा को बदलने की कोशिश करने से वर्तमान संस्करण के साथ एक ही परिणाम नहीं होगाParcelable कोटलीन प्लगइन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 का उपयोग करेंअपने मॉडल / डेटा वर्ग के शीर्ष पर एनोटेशन का
  • कोटलिन के नवीनतम संस्करण का उपयोग करें
  • अपने ऐप मॉड्यूल में कोटलिन एंड्रॉइड एक्सटेंशन के नवीनतम संस्करण का उपयोग करें

उदाहरण :

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

3

दुर्भाग्य से एक इंटरफ़ेस में एक वास्तविक क्षेत्र डालने के लिए कोटलिन में कोई रास्ता नहीं है, इसलिए आप इसे इंटरफ़ेस-एडेप्टर से मुफ्त में प्राप्त नहीं कर सकते हैं: 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)

इससे त्रुटि "क्लास 'MyClass' सार नहीं है और सार सदस्य सार्वजनिक सार मज़ा writeToParcel को लागू नहीं करता है (गंतव्य: पार्सल !, झंडे: इंट): यूनिट android.os.Parcelable में परिभाषित
PhillyTheThrilly

2

आप इसे @Parcelizeएनोटेशन का उपयोग करके कर सकते हैं । यह एक ऑटोमैटिक पार्सलेबल इम्प्लीमेंटेशन जनरेटर है।

सबसे पहले, आपको इसे अपने मॉड्यूल के 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ब्लॉक।


1

Kotlin ने अपने @Parcel एनोटेशन के साथ Android लानत में Parcelization की पूरी प्रक्रिया को आसान बना दिया है।

ऐसा करने के लिए

चरण 1. अपने ऐप मॉड्यूल ग्रेडेल में कोटलिन एक्सटेंशन जोड़ें

चरण 2। प्रयोगात्मक जोड़ें = सही क्योंकि यह सुविधा अब भी प्रयोग में है।

AndroidExtensions {प्रयोगात्मक = सच}

चरण 3. @Parcel के साथ डेटा वर्ग की घोषणा करें

यहाँ @Parcel उपयोग पर एक सरल उदाहरण है


0

एक प्लगइन है लेकिन हमेशा के रूप में अद्यतन नहीं है जैसा कि कोटलिन विकसित हो रहा है: https://plugins.jetbrains.com/plug//86

वैकल्पिक: मेरे पास उपयोग Parcelableऔर सूचियों के कस्टम डेटा वर्ग का एक कार्यशील उदाहरण है :

सूचियों के साथ पार्सलबल का उपयोग करने वाले डेटा वर्ग:

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

आशा करता हूँ की ये काम करेगा!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.