Ayrıştırılabilir uygulama oluşturma aracı

kotlin-parcelize eklentisi, Parcelable uygulama oluşturucu sağlar.

Parcelable desteğini eklemek için Gradle eklentisini uygulamanızın build.gradle dosyasına ekleyin:

Modern

plugins {
    id 'kotlin-parcelize'
}

Kotlin

plugins {
    id("kotlin-parcelize")
}

Bir sınıfa @Parcelize ile not eklediğinizde, aşağıdaki örnekte gösterildiği gibi otomatik olarak bir Parcelable uygulaması oluşturulur:

// import kotlinx.parcelize.Parcelize

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

@Parcelize, tüm serileştirilmiş özelliklerin birincil oluşturucuda bildirilmesini gerektirir. Eklenti, sınıf gövdesinde destek alanı bildirilmiş her özellik için uyarı verir. Ayrıca, birincil oluşturucu parametrelerinden bazıları özellik değilse @Parcelize uygulayamazsınız.

Sınıfınız daha gelişmiş bir serileştirme mantığı gerektiriyorsa bunu tamamlayıcı bir sınıfın içinde yazın:

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

Desteklenen türler

@Parcelize çok çeşitli türleri destekler:

  • Temel türler (ve bunların kutulanmış sürümleri)
  • Nesneler ve enums
  • String, CharSequence
  • Duration
  • Exception
  • Size, SizeF, Bundle, IBinder, IInterface, FileDescriptor
  • SparseArray, SparseIntArray, SparseLongArray, SparseBooleanArray
  • Tüm Serializable (Date dahil) ve Parcelable uygulamaları
  • Desteklenen tüm türlerdeki koleksiyonlar: List (ArrayList ile eşlenir), Set (LinkedHashSet ile eşlenir), Map (LinkedHashMap ile eşlenir)
    • Ayrıca bir dizi somut uygulama: ArrayList, LinkedList, SortedSet, NavigableSet, HashSet, LinkedHashSet, TreeSet, SortedMap, NavigableMap, HashMap, LinkedHashMap, TreeMap, ConcurrentHashMap
  • Desteklenen tüm türlerin dizileri
  • Desteklenen tüm türlerin null değer atanabilir sürümleri

Özel Parcelers

Türünüz doğrudan desteklenmiyorsa bunun için bir Parceler eşleme nesnesi yazabilirsiniz.

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 veya @WriteWith notlarını kullanarak harici ayrıştırıcılar uygulayabilirsiniz:

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

Parcel'dan veri oluşturma

Java kodunda CREATOR alanına doğrudan erişebilirsiniz.

class UserCreator {
    static User fromParcel(Parcel parcel) {
        return User.CREATOR.createFromParcel(parcel);
    }
}

Kotlin'de CREATOR alanını doğrudan kullanamazsınız. Bunun yerine kotlinx.parcelize.parcelableCreator kullanın.

// import kotlinx.parcelize.parcelableCreator

fun userFromParcel(parcel: Parcel): User {
    return parcelableCreator<User>().createFromParcel(parcel)
}

Özelliklerin serileştirilmesini atlama

Bazı mülklerin paketlenmesini atlamak istiyorsanız @IgnoredOnParcel ek açıklamasını kullanın. Ayrıca, özelliğin serileştirilmemesiyle ilgili uyarıları devre dışı bırakmak için bir sınıfın gövdesindeki özelliklerde de kullanılabilir. @IgnoredOnParcel ile açıklama eklenmiş oluşturucu özelliklerinin varsayılan bir değeri olmalıdır.

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

Bir özelliği serileştirmek için android.os.Parcel.writeValue kullanın.

Parcelize'ın bir özellik için Parcel.writeValue kullanmasını sağlamak üzere türü @RawValue ile açıklama ekleyebilirsiniz.

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

Mülkün değeri Android tarafından doğal olarak desteklenmiyorsa bu işlem çalışma zamanında başarısız olabilir.

Parcelize, özelliği serileştirmenin başka bir yolu olmadığında da bu açıklamayı kullanmanızı gerektirebilir.

Sızdırmaz sınıflar ve sızdırmaz arayüzlerle paketleme

Parcelize, paketlenecek sınıfın soyut olmamasını gerektirir. Bu sınırlama, kapalı sınıflar için geçerli değildir. @Parcelize ek açıklaması kapalı bir sınıfta kullanıldığında, türetilen sınıflar için tekrarlanması gerekmez.

@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 Multiplatform için Parcelize'ı ayarlama

Kotlin 2.0'dan önce, Parcelize ek açıklamalarına expect ve actual ile takma ad vererek Parcelize'ı kullanabiliyordunuz:

// Common code
package example

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY)
expect annotation class MyParcelize()

expect interface MyParcelable

@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.SOURCE)
expect annotation class MyIgnoredOnParcel()

@MyParcelize
class MyClass(
    val x: String,
    @MyIgnoredOnParcel val y: String = ""
): MyParcelable

// Platform code
package example

actual typealias MyParcelize = kotlinx.parcelize.Parcelize
actual typealias MyParcelable = android.os.Parcelable
actual typealias MyIgnoredOnParcel = kotlinx.parcelize.IgnoredOnParcel

Kotlin 2.0 ve sonraki sürümlerde, eklentileri tetikleyen takma ad oluşturma ek açıklamaları desteklenmez. Bunu önlemek için eklentiye additionalAnnotation parametresi olarak yeni bir Parcelize ek açıklaması sağlayın.

// Gradle build configuration
kotlin {
    androidTarget {
        compilerOptions {
            // ...
            freeCompilerArgs.addAll("-P", "plugin:org.jetbrains.kotlin.parcelize:additionalAnnotation=example.MyParcelize")
        }
    }
}

// Common code
// package example

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY)
// No `expect` keyword here
annotation class MyParcelize()

expect interface MyParcelable

@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.SOURCE)
expect annotation class MyIgnoredOnParcel()

@MyParcelize
class MyClass(
    val x: String,
    @MyIgnoredOnParcel val y: String = ""
) : MyParcelable

// Platform code
// package example

// No typealias for MyParcelize here
actual typealias MyParcelable = android.os.Parcelable
actual typealias MyIgnoredOnParcel = kotlinx.parcelize.IgnoredOnParcel

Parcel arayüzü yalnızca Android'de kullanılabildiğinden Parcelize, diğer platformlarda herhangi bir kod oluşturmaz. Bu nedenle, bu platformlardaki actual uygulamaları boş olabilir. Ayrıca, ortak kodda Parcel sınıfına referans verilmesini gerektiren herhangi bir ek açıklama kullanmak da mümkün değildir. Örneğin, @WriteWith.

Deneysel özellikler

Veri sınıfı serileştiricisi

Kotlin 2.1.0'dan beri kullanılabilir.

DataClass ek açıklaması, veri sınıflarının Parcelize ile ek açıklama eklenmiş gibi seri hale getirilmesine olanak tanır. Bu ek açıklama için kotlinx.parcelize.Experimental özelliğinin etkinleştirilmesi gerekir.

// @file:OptIn(kotlinx.parcelize.Experimental::class)

data class C(val a: Int, val b: String)

@Parcelize
class P(val c: @DataClass C) : Parcelable

Birincil oluşturucuya ve tüm özelliklerine Parcelable sınıfından erişilebilmelidir. Ayrıca, veri sınıfının tüm birincil oluşturucu özellikleri Parcelize tarafından desteklenmelidir. Seçilirse Custom Parcelers, veri sınıfında değil Parcelable sınıfında belirtilmelidir. Veri sınıfı aynı anda Serializable uyguluyorsa @DataClass notu öncelikli olur: android.os.Parcel.writeSerializable kullanılmaz.

Bunun pratik bir kullanım alanı, kotlin.Pair öğesini serileştirmektir. Bir diğer faydalı örnek, çok platformlu kodu basitleştirmektir: Ortak kod, veri katmanını veri sınıfları olarak tanımlayabilir. Bu durumda Android kodu, ortak kodda Android'e özgü ek açıklamalar ve tür takma adları ihtiyacını ortadan kaldırarak serileştirme mantığıyla artırılabilir.

// Common code:
data class MyData(val x: String, val y: MoreData)
data class MoreData(val a: String, val b: Int)

// Platform code:
@OptIn(kotlinx.parcelize.Experimental::class)
@Parcelize
class DataWrapper(val wrapped: @DataClass MyData) : Parcelable

Birincil oluşturucuda val veya var olmayan parametreler

Kotlin 2.1.0'dan beri kullanılabilir.

Bu özelliği etkinleştirmek için paketleme eklentisi bağımsız değişkenlerine experimentalCodeGeneration=true ekleyin.

kotlin {
    compilerOptions {
        // ...
        freeCompilerArgs.addAll("-P", "plugin:org.jetbrains.kotlin.parcelize:experimentalCodeGeneration=true")
    }
}

Bu özellik, birincil oluşturucu bağımsız değişkenlerinin val veya var olması gerektiği kısıtlamasını kaldırır. Bu, daha önce open özelliklerinin kullanılmasını gerektiren, kalıtımla birlikte parcelize kullanmanın bir zorluğunu çözer.

// base parcelize
@Parcelize
open class Base(open val s: String) : Parcelable

@Parcelize
class Derived(
    val x: Int,
    // all arguments have to be `val` or `var` so we need to override
    // to not introduce new property name
    override val s: String
) : Base(s)

// experimental code generation enabled
@Parcelize
open class Base(val s: String): Parcelable

@Parcelize
class Derived(val x: Int, s: String): Base(s)

Bu tür parametrelerin yalnızca temel sınıf oluşturucusunun bağımsız değişkenlerinde kullanılmasına izin verilir. Sınıfın gövdesinde bunlara referans verilmesine izin verilmez.

@Parcelize
class Derived(s: String): Base(s) { // allowed
    @IgnoredOnParcel
    val x: String = s // ERROR: not allowed.
    init {
        println(s) // ERROR: not allowed
    }
}

Geri bildirim

kotlin-parcelizeGradle eklentisi ile ilgili herhangi bir sorunla karşılaşırsanız hata bildiriminde bulunabilirsiniz.