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

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

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

Groovy

plugins {
    id 'kotlin-parcelize'
}

Kotlin

plugins {
    id("kotlin-parcelize")
}

Bir sınıfı @Parcelize ile ek açıklamayla işaretlediğ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 tanımlanmasını gerektirir. Eklenti, sınıf gövdesinde tanımlanmış bir destek alanı içeren her mülk için uyarı verir. Ayrıca, birincil kurucu parametrelerinden bazıları özellik değilse @Parcelize'ü uygulayamazsınız.

Sınıfınız için daha gelişmiş bir serileştirme mantığı gerekiyorsa bunu bir tamamlayıcı sınıfın içine 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 kutulu sürümleri)
  • Nesneler ve enum'lar
  • 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 bazı somut uygulamalar: ArrayList, LinkedList, SortedSet, NavigableSet, HashSet, LinkedHashSet, TreeSet, SortedMap, NavigableMap, HashMap, LinkedHashMap, TreeMap, ConcurrentHashMap
  • Desteklenen tüm türlerdeki diziler
  • Desteklenen tüm türlerin boş değerli sürümleri

Özel Parceler'ler

Türünüz doğrudan desteklenmiyorsa bunun için 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 ek açıklamalarını kullanarak harici paketleyiciler 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

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

Serileştirmeden özellikleri atla

Bazı mülkleri parsellemeye dahil etmek istemiyorsanız @IgnoredOnParcel ek açıklamasını kullanın. Ayrıca, sınıfın gövdesindeki mülklerde, mülkün serileştirilmediğiyle ilgili uyarıları devre dışı bırakmak için de kullanılabilir. @IgnoredOnParcel ek açıklamasına sahip oluşturucu özellikleri, varsayılan bir değere sahip 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 mülkü serileştirmek için android.os.Parcel.writeValue'i kullanma

Bir türün üzerine @RawValue ekleyerek Parcelize'in söz konusu mülk için Parcel.writeValue kullanmasını sağlayabilirsiniz.

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

Parçalara ayırma işlemi, mülkü serileştirmenin başka bir yolu olmadığında bu ek açıklamayı kullanmanızı da gerektirebilir.

Mühürlü sınıflar ve mühürlü arayüzler ile paketleme

Parselize etmek için bir sınıfın soyut olmaması gerekir. Bu sınırlama, mühürlü sınıflar için geçerli değildir. @Parcelize ek açıklaması, mühürlenmiş bir sınıfta kullanıldığında, türetilmiş 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 çoklu platformu için Parselize'ı kurun

Kotlin 2.0'dan önce, Parcelize ek açıklamalarını expect ve actual ile takma adlandırarak Parcelize'i 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 ek açıklamaları desteklenmez. Bu sorunu önlemek için eklentiye additionalAnnotation parametresi olarak yeni bir Parcelize ek açıklaması ekleyin.

// 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 kod oluşturmaz. Bu nedenle, bu platformlardaki actual uygulamaları boş olabilir. Ayrıca, ortak kodda Parcel sınıfına referans vermeyi gerektiren ek açıklamaların (ör. @WriteWith) kullanılması da mümkün değildir.

Deneysel özellikler

Veri sınıfı serileştirici

Kotlin 2.1.0'dan beri kullanılabilir.

DataClass ek açıklaması, veri sınıflarını Parcelize ile ek açıklama eklemişler gibi serileştirmeye olanak tanır. Bu ek açıklama için kotlinx.parcelize.Experimental etkinleştirmesi 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 kurucu özellikleri Parcelize tarafından desteklenmelidir. Seçilen özel paketleyiciler, veri sınıfında değil Parcelable sınıfında belirtilmelidir. Veri sınıfı aynı anda Serializable özelliğini uygularsa @DataClass ek açıklaması öncelikli olur: android.os.Parcel.writeSerializable kullanılmaz.

Bunun pratik bir kullanım alanı, kotlin.Pair öğesini serileştirmek olabilir. Yararlı bir örnek de çoklu platform kodunun basitleştirilmesidir: Ortak kod, veri katmanını veri sınıfları olarak tanımlayabilir. Android kodu daha sonra bu sınıfları serileştirme mantığıyla genişletebilir. Böylece, ortak kodda Android'e özgü ek açıklamalara ve tür takma adlarına gerek kalmaz.

// 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 kurucuda val veya var olmayan parametreler

Kotlin 2.1.0'dan beri kullanılabilir.

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

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

Bu özellik, birincil kurucu bağımsız değişkenlerinin val veya var olmasıyla ilgili kısıtlamayı kaldırır. Bu, daha önce open özelliklerinin kullanılmasını gerektiren, devralma ile parcelize kullanmanın bir sorununu çö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 kurucusunun 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-parcelize Gradle eklentisiyle ilgili herhangi bir sorunla karşılaşırsanız hata kaydı oluşturabilirsiniz.