带有@Parcelize 注释的 RealmList [英] RealmList with @Parcelize annotation

查看:24
本文介绍了带有@Parcelize 注释的 RealmList的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将 Kotlin 1.1.4 添加的新 @Parcelize 注释与包含 RealmList 属性的 Realm 对象一起使用.

I'm trying to use the new @Parcelize annotation added with Kotlin 1.1.4 with a Realm objet containing a RealmList attribute.

@Parcelize
@RealmClass
open class Garage(
        var name: String? = null,
        var cars: RealmList<Car> = RealmList()
) : Parcelable, RealmModel

由于注释不支持 RealmList 并假设 @Parcelize 是专门用来避免创建方法的,那么支持 RealmList 的解决方案是什么代码> ?

As RealmList is not supported by the annotation and assuming that @Parcelize is there specially to avoid creating methods what would be the solution to support RealmList ?

提前致谢

推荐答案

利用 Type Parcelers 和 @WriteWith 注释的强大功能,可以创建一个 RealmList 类型 Parceler 来为您处理这种情况:

Using the power of Type Parcelers and @WriteWith annotation, it is possible to create a RealmList type parceler that can handle this scenario for you:

使用以下代码:

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

你可以像这样定义一个接口:

You can define an interface like this:

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 创建一个特定的 Parceler,如下所示:

Where you'll need to create a specific parceler for the RealmList<Car> like this:

object CarRealmListParceler: RealmListParceler<Car> {
    override val clazz: Class<Car>
        get() = Car::class.java
}

但是有了它,现在您可以执行以下操作:

but with that, now you can do the following:

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

This way you don't need to manually write the Parceler logic.

原始答案:

以下应该有效:

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

只要你还添加以下扩展功能:

As long as you also add following extension functions:

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
}

这篇关于带有@Parcelize 注释的 RealmList的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆