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,CharSequenceDurationExceptionSize,SizeF,Bundle,IBinder,IInterface,FileDescriptorSparseArray,SparseIntArray,SparseLongArray,SparseBooleanArray- Tüm
Serializable(Datedahil) veParcelableuygulamaları - Desteklenen tüm türlerdeki koleksiyonlar:
List(ArrayListile eşlenir),Set(LinkedHashSetile eşlenir),Map(LinkedHashMapile eşlenir)- Ayrıca bir dizi somut uygulama:
ArrayList,LinkedList,SortedSet,NavigableSet,HashSet,LinkedHashSet,TreeSet,SortedMap,NavigableMap,HashMap,LinkedHashMap,TreeMap,ConcurrentHashMap
- Ayrıca bir dizi somut uygulama:
- 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.