带有@Parcelize 注解的RealmList
RealmList with @Parcelize annotation
我正在尝试将 Kotlin 1.1.4 添加的新 @Parcelize
注释与包含 RealmList 属性的 Realm 对象一起使用。
@Parcelize
@RealmClass
open class Garage(
var name: String? = null,
var cars: RealmList<Car> = RealmList()
) : Parcelable, RealmModel
由于注释不支持 RealmList
并且假设 @Parcelize
是专门用来避免创建方法的,支持 RealmList
的解决方案是什么?
提前致谢
编辑:
利用 Type Parcelers 和 @WriteWith
annotation 的强大功能,可以创建一个 RealmList 类型的 parceler 来为您处理这种情况:
使用以下代码:
fun <T> Parcel.readRealmList(clazz: Class<T>): RealmList<T>?
where T : RealmModel,
T : Parcelable = when {
readInt() > 0 -> RealmList<T>().also { list ->
repeat(readInt()) {
list.add(readParcelable(clazz.classLoader))
}
}
else -> null
}
fun <T> Parcel.writeRealmList(realmList: RealmList<T>?, clazz: Class<T>)
where T : RealmModel,
T : Parcelable {
writeInt(when {
realmList == null -> 0
else -> 1
})
if (realmList != null) {
writeInt(realmList.size)
for (t in realmList) {
writeParcelable(t, 0)
}
}
}
你可以这样定义接口:
interface RealmListParceler<T>: Parceler<RealmList<T>?> where T: RealmModel, T: Parcelable {
override fun create(parcel: Parcel): RealmList<T>? = parcel.readRealmList(clazz)
override fun RealmList<T>?.write(parcel: Parcel, flags: Int) {
parcel.writeRealmList(this, clazz)
}
val clazz : Class<T>
}
您需要像这样为 RealmList<Car>
创建一个特定的 parceler:
object CarRealmListParceler: RealmListParceler<Car> {
override val clazz: Class<Car>
get() = Car::class.java
}
但是现在您可以执行以下操作:
@Parcelize
@RealmClass
open class Garage(
var name: String? = null,
var cars: @WriteWith<CarRealmListParceler> RealmList<Car> = RealmList()
) : Parcelable, RealmModel
和
@Parcelize
@RealmClass
open class Car(
..
): RealmModel, Parcelable {
...
}
这样就不需要手动编写Parceler逻辑了。
原始答案:
以下应该有效:
@Parcelize
open class Garage: RealmObject(), Parcelable {
var name: String? = null
var cars: RealmList<Car>? = null
companion object : Parceler<Garage> {
override fun Garage.write(parcel: Parcel, flags: Int) {
parcel.writeNullableString(name)
parcel.writeRealmList(cars)
}
override fun create(parcel: Parcel): Garage = Garage().apply {
name = parcel.readNullableString()
cars = parcel.readRealmList()
}
}
}
只要你还添加以下扩展功能:
inline fun <reified T> Parcel.writeRealmList(realmList: RealmList<T>?)
where T : RealmModel,
T : Parcelable {
writeInt(when {
realmList == null -> 0
else -> 1
})
if (realmList != null) {
writeInt(realmList.size)
for (t in realmList) {
writeParcelable(t, 0)
}
}
}
inline fun <reified T> Parcel.readRealmList(): RealmList<T>?
where T : RealmModel,
T : Parcelable = when {
readInt() > 0 -> RealmList<T>().also { list ->
repeat(readInt()) {
list.add(readParcelable(T::class.java.classLoader))
}
}
else -> null
}
还有
fun Parcel.writeNullableString(string: String?) {
writeInt(when {
string == null -> 0
else -> 1
})
if (string != null) {
writeString(string)
}
}
fun Parcel.readNullableString(): String? = when {
readInt() > 0 -> readString()
else -> null
}
我正在尝试将 Kotlin 1.1.4 添加的新 @Parcelize
注释与包含 RealmList 属性的 Realm 对象一起使用。
@Parcelize
@RealmClass
open class Garage(
var name: String? = null,
var cars: RealmList<Car> = RealmList()
) : Parcelable, RealmModel
由于注释不支持 RealmList
并且假设 @Parcelize
是专门用来避免创建方法的,支持 RealmList
的解决方案是什么?
提前致谢
编辑:
利用 Type Parcelers 和 @WriteWith
annotation 的强大功能,可以创建一个 RealmList 类型的 parceler 来为您处理这种情况:
使用以下代码:
fun <T> Parcel.readRealmList(clazz: Class<T>): RealmList<T>?
where T : RealmModel,
T : Parcelable = when {
readInt() > 0 -> RealmList<T>().also { list ->
repeat(readInt()) {
list.add(readParcelable(clazz.classLoader))
}
}
else -> null
}
fun <T> Parcel.writeRealmList(realmList: RealmList<T>?, clazz: Class<T>)
where T : RealmModel,
T : Parcelable {
writeInt(when {
realmList == null -> 0
else -> 1
})
if (realmList != null) {
writeInt(realmList.size)
for (t in realmList) {
writeParcelable(t, 0)
}
}
}
你可以这样定义接口:
interface RealmListParceler<T>: Parceler<RealmList<T>?> where T: RealmModel, T: Parcelable {
override fun create(parcel: Parcel): RealmList<T>? = parcel.readRealmList(clazz)
override fun RealmList<T>?.write(parcel: Parcel, flags: Int) {
parcel.writeRealmList(this, clazz)
}
val clazz : Class<T>
}
您需要像这样为 RealmList<Car>
创建一个特定的 parceler:
object CarRealmListParceler: RealmListParceler<Car> {
override val clazz: Class<Car>
get() = Car::class.java
}
但是现在您可以执行以下操作:
@Parcelize
@RealmClass
open class Garage(
var name: String? = null,
var cars: @WriteWith<CarRealmListParceler> RealmList<Car> = RealmList()
) : Parcelable, RealmModel
和
@Parcelize
@RealmClass
open class Car(
..
): RealmModel, Parcelable {
...
}
这样就不需要手动编写Parceler逻辑了。
原始答案:
以下应该有效:
@Parcelize
open class Garage: RealmObject(), Parcelable {
var name: String? = null
var cars: RealmList<Car>? = null
companion object : Parceler<Garage> {
override fun Garage.write(parcel: Parcel, flags: Int) {
parcel.writeNullableString(name)
parcel.writeRealmList(cars)
}
override fun create(parcel: Parcel): Garage = Garage().apply {
name = parcel.readNullableString()
cars = parcel.readRealmList()
}
}
}
只要你还添加以下扩展功能:
inline fun <reified T> Parcel.writeRealmList(realmList: RealmList<T>?)
where T : RealmModel,
T : Parcelable {
writeInt(when {
realmList == null -> 0
else -> 1
})
if (realmList != null) {
writeInt(realmList.size)
for (t in realmList) {
writeParcelable(t, 0)
}
}
}
inline fun <reified T> Parcel.readRealmList(): RealmList<T>?
where T : RealmModel,
T : Parcelable = when {
readInt() > 0 -> RealmList<T>().also { list ->
repeat(readInt()) {
list.add(readParcelable(T::class.java.classLoader))
}
}
else -> null
}
还有
fun Parcel.writeNullableString(string: String?) {
writeInt(when {
string == null -> 0
else -> 1
})
if (string != null) {
writeString(string)
}
}
fun Parcel.readNullableString(): String? = when {
readInt() > 0 -> readString()
else -> null
}