Trình bổ trợ kotlin-parcelize
cung cấp một trình tạo lượt triển khai Parcelable
.
Để hỗ trợ Parcelable
, hãy thêm trình bổ trợ Gradle vào tệp build.gradle
của ứng dụng:
Groovy
plugins { id 'kotlin-parcelize' }
Kotlin
plugins { id("kotlin-parcelize") }
Khi bạn chú thích một lớp (class) bằng @Parcelize
, phương thức triển khai Parcelable
sẽ tự động được tạo, như trong ví dụ sau:
import kotlinx.parcelize.Parcelize
@Parcelize
class User(val firstName: String, val lastName: String, val age: Int): Parcelable
@Parcelize
đòi hỏi khai báo tất cả thuộc tính tuần tự trong hàm khởi tạo chính. Trình bổ trợ này cảnh báo về từng thuộc tính có một trường sao lưu được khai báo trong nội dung lớp. Ngoài ra, bạn không thể áp dụng @Parcelize
nếu một số tham số của hàm khởi tạo chính không phải là thuộc tính.
Nếu lớp của bạn yêu cầu logic tuần tự hoá nâng cao hơn, hãy ghi lớp này vào trong lớp đồng hành (companion class):
@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
}
}
}
Các kiểu được hỗ trợ
@Parcelize
hỗ trợ nhiều kiểu:
- Kiểu nguyên bản (và các phiên bản đóng hộp)
- Đối tượng và enum
String
,CharSequence
Duration
Exception
Size
,SizeF
,Bundle
,IBinder
,IInterface
,FileDescriptor
SparseArray
,SparseIntArray
,SparseLongArray
,SparseBooleanArray
- Tất cả cách triển khai
Serializable
(bao gồm cảDate
) vàParcelable
- Bộ sưu tập toàn bộ kiểu được hỗ trợ:
List
(được ánh xạ tớiArrayList
),Set
(được ánh xạ tớiLinkedHashSet
),Map
(được ánh xạ tớiLinkedHashMap
)- Ngoài ra, có một số cách triển khai cụ thể:
ArrayList
,LinkedList
,SortedSet
,NavigableSet
,HashSet
,LinkedHashSet
,TreeSet
,SortedMap
,NavigableMap
,HashMap
,LinkedHashMap
,TreeMap
,ConcurrentHashMap
- Ngoài ra, có một số cách triển khai cụ thể:
- Mảng (array) thuộc mọi kiểu được hỗ trợ
- Phiên bản có tính chất rỗng của mọi kiểu được hỗ trợ
Parceler
tuỳ chỉnh
Nếu kiểu của bạn không được hỗ trợ trực tiếp, bạn có thể viết một đối tượng ánh xạ Parceler
cho kiểu đó.
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)
}
}
Bạn có thể áp dụng các trình đóng gói (parceler) bên ngoài bằng chú thích @TypeParceler
hoặc @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
Bỏ qua các thuộc tính khỏi quá trình chuyển đổi tuần tự
Nếu bạn muốn bỏ qua việc phân loại một số thuộc tính, hãy sử dụng thuộc tính
Chú giải @IgnoredOnParcel
. Bạn cũng có thể dùng công cụ này trên các tài sản trong
phần nội dung của lớp để tắt tiếng các cảnh báo về việc thuộc tính không được chuyển đổi tuần tự.
Thuộc tính hàm khởi tạo được chú thích bằng @IgnoredOnParcel
phải có giá trị mặc định
giá trị.
@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
}
Sử dụng android.os.Parcel.writeValue để chuyển đổi tuần tự một thuộc tính
Bạn có thể chú thích một loại bằng @RawValue
để sử dụng Phân vùng
Parcel.writeValue
cho tài sản đó.
@Parcelize
class MyClass(val external: @RawValue ExternalClass): Parcelable
Thao tác này có thể không thực hiện được trong thời gian chạy nếu giá trị của thuộc tính không được Android hỗ trợ vốn có.
Bạn cũng có thể phải sử dụng chú thích này khi không có chú thích nào khác để tuần tự hoá thuộc tính.
Đóng gói bằng các lớp kín và giao diện kín
Việc phân vùng yêu cầu phải phân vùng một lớp sao cho không phải là lớp trừu tượng. Giới hạn này
không được lưu giữ đối với các lớp kín. Khi chú thích @Parcelize
được sử dụng trên một lớp kín, bạn không cần lặp lại chú thích này cho các lớp phái sinh.
@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
Phản hồi
Nếu gặp vấn đề với trình bổ trợ kotlin-parcelize
cho Gradle, bạn có thể báo cáo lỗi.