带@Parcelize批注的RealmList [英] RealmList with @Parcelize annotation

查看:94
本文介绍了带@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<Car>创建一个特定的包裹,如下所示:

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.

原始答案:

ORIGINAL ANSWER:

以下应该有效:

@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天全站免登陆