מחולל הטמעה שניתן למנות

הפלאגין kotlin-parcelize מספקת Parcelable מחולל יישומים.

כדי לכלול תמיכה ב-Parcelable, צריך להוסיף את הפלאגין של Gradle אל קובץ build.gradle של האפליקציה:

Groovy

plugins {
    id 'kotlin-parcelize'
}

Kotlin

plugins {
    id("kotlin-parcelize")
}

כשמוסיפים הערות לכיתה באמצעות @Parcelize, הטמעה של Parcelable נוצרת באופן אוטומטי, כמו בדוגמה הבאה:

import kotlinx.parcelize.Parcelize

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

ל-@Parcelize נדרשת הצהרה על כל המאפיינים שעברו סריאליזציה ב- הראשי, הפלאגין מפרסם אזהרה בכל נכס עם שדה גיבוי שמוצהר בגוף הכיתה. כמו כן, לא ניתן להחיל את @Parcelize אם חלק מהפרמטרים של ה-constructor הראשי ולא נכסים.

אם בכיתה שלכם נדרשת לוגיקה מתקדמת יותר של שרשור, כתבו אותה בכיתה נלווית:

@Parcelize
data class User(val firstName: String, val lastName: String, val age: Int) : Parcelable {
    private companion object : Parceler<User> {
        override fun User.write(parcel: Parcel, flags: Int) {
            // Custom write implementation
        }

        override fun create(parcel: Parcel): User {
            // Custom read implementation
        }
    }
}

סוגים נתמכים

ב-@Parcelize יש תמיכה במגוון רחב של סוגים:

  • סוגי נתונים פרימיטיביים (וגרסאות ה-boxed שלהם)
  • אובייקטים וטיפוסים בני מנייה (enums)
  • String, CharSequence
  • Duration
  • Exception
  • Size, SizeF, Bundle, IBinder, IInterface, FileDescriptor
  • SparseArray, SparseIntArray, SparseLongArray, SparseBooleanArray
  • כל ההטמעות של Serializable (כולל Date) ו-Parcelable
  • אוספים של כל הסוגים הנתמכים: List (הממופה ל-ArrayList), Set (הממופה ל-LinkedHashSet), Map (הממופה ל-LinkedHashMap)
    • וגם מספר הטמעות קונקרטיות: ArrayList, LinkedList, SortedSet, NavigableSet, HashSet, LinkedHashSet, TreeSet, SortedMap, NavigableMap, HashMap, LinkedHashMap, TreeMap, ConcurrentHashMap
  • מערכים של כל הסוגים הנתמכים
  • גרסאות איפוס של כל הסוגים הנתמכים

Parceler בהתאמה אישית

אם אין תמיכה בסוג שלך באופן ישיר, אפשר לכתוב Parceler למיפוי מבוסס-אובייקטים.

class ExternalClass(val value: Int)

object ExternalClassParceler : Parceler<ExternalClass> {
    override fun create(parcel: Parcel) = ExternalClass(parcel.readInt())

    override fun ExternalClass.write(parcel: Parcel, flags: Int) {
        parcel.writeInt(value)
    }
}

אפשר להחיל מגרשים חיצוניים באמצעות @TypeParceler או @WriteWith הערות:

// Class-local parceler
@Parcelize
@TypeParceler<ExternalClass, ExternalClassParceler>()
class MyClass(val external: ExternalClass) : Parcelable

// Property-local parceler
@Parcelize
class MyClass(@TypeParceler<ExternalClass, ExternalClassParceler>() val external: ExternalClass) : Parcelable

// Type-local parceler
@Parcelize
class MyClass(val external: @WriteWith<ExternalClassParceler>() ExternalClass) : Parcelable

דילוג על מאפיינים מעיבוד סריאלי

אם רוצים לדלג על חלוקה של נכס מסוים, צריך להשתמש הערה אחת (@IgnoredOnParcel). אפשר להשתמש בו גם בנכסים בתוך הגוף של הכיתה כדי להשתיק אזהרות על כך שאין סריאליזציה לנכס. למאפייני הבנייה עם הערות @IgnoredOnParcel חייבת להיות ברירת מחדל עם ערך מסוים.

@Parcelize
class MyClass(
    val include: String,
    // Don't serialize this property
    @IgnoredOnParcel val ignore: String = "default"
): Parcelable {
    // Silence a warning
    @IgnoredOnParcel
    val computed: String = include + ignore
}

שימוש ב-android.os.Parcel.writeValue לסריאליזציה של נכס

כדי להשתמש ב'חבילה', אפשר להוסיף הערות לסוג @RawValue Parcel.writeValue לנכס הזה.

@Parcelize
class MyClass(val external: @RawValue ExternalClass): Parcelable

פעולה זו עלולה להיכשל בזמן הריצה אם הערך של הנכס אינו נתמך במקור ב-Android.

יכול להיות שתצטרכו להשתמש בהערה הזו גם ב-Parcelize כשאין דרך אחרת לסריאליזציה של הנכס.

חלוקה לחבילות באמצעות מחלקות אטומות וממשקים אטומים

כדי להשתמש במאפיין 'חלקים', חובה להגדיר מחלקה כדי שהנתונים לא יהיו מופשטים. ההגבלה הזאת לא לשמור עבור כיתות חתומות. כאשר נעשה שימוש בהערה @Parcelize ב מחלקה אטומה, לא צריך לחזור עליו עבור המחלקות הנגזרות.

@Parcelize
sealed class SealedClass: Parcelable {
    class A(val a: String): SealedClass()
    class B(val b: Int): SealedClass()
}

@Parcelize
class MyClass(val a: SealedClass.A, val b: SealedClass.B, val c: SealedClass): Parcelable

משוב

אם נתקלת בבעיות בפלאגין kotlin-parcelize Gradle, אפשר לבצע את הפעולות הבאות דיווח על באג.