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ıfa @Parcelize kodunu 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 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ürlerin 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ürlerin dizileri
  • Desteklenen tüm türlerin boş değerli sürümleri

Özel Parceler'ler

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

Özellikleri serileştirmeden atlama

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 ile ek açıklama eklenmiş kurucu ö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ü seri hale getirmek için android.os.Parcel.WriteValue kullanın

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

Özelliğin değeri Android tarafından yerel 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

Paketleme işlemi için, paketlenecek 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ürlü bir sınıfta kullanıldığında, türetme 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 çok platformlu için Parcelize'i ayarlama

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. Bunu atlatmak 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 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çıklama, veri sınıflarının Parcelize ile ek açıklama yapılmış gibi serileştirilmesine 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. Buna ek olarak, veri sınıfının tüm birincil oluşturucu ö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 uygularsa @DataClass ek açıklama ö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, val veya var olması gereken birincil kurucu bağımsız değişkenlerindeki 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.