RealmObject和Parcelable

8

在Android上使用Realm,我有一个类:

public class Entry extends RealmObject implements Parcelable {
    ...
}

Parcelable接口包含了像describeContents()writeToParcel()这样的方法,而RealmObjects不应该有除了getter和setter之外的方法:

错误:(81, 17)错误:模型类中只应定义getter和setter

我该如何让这两者一起工作?有没有比创建一个单独的类(也许像RealmEntry这样的类)更好的方法?这样做会导致很多重复的代码。


你为什么要尝试使用Parcelable对象和Realm? - Orgmir
1
我使用Parcelable来在配置更改(设备旋转)时保留对象,并使用Realm将对象存储到数据库中。 - frankelot
1
在配置更改后重新查询数据库不是更有意义吗?考虑到您正在使用带有缓存机制的RealmDB,这甚至可能更快。 - A. Steenbergen
5个回答

10

2016年5月更新:除非您已经使用过Parceler,否则此答案已经过时。@Henrique de Sousa的解决方案更好。


实际上,有一种解决方法。 如果您愿意使用第三方库(Parceler)生成Parcelable,则可以获得所需的结果。 请参见我在另一个问题中的回答,下面是方便引用的内容。

使用Parceler v0.2.16,您可以这样做:

@RealmClass      // required if using JDK 1.6 (unrelated to Parceler issue)
@Parcel(value = Parcel.Serialization.BEAN, analyze = { Feed.class })
public class Feed extends RealmObject {
    // ...
}

在所有地方使用 Parcels.wrap(Feed.class, feed)替代 Parcels.wrap(feed),否则您的应用程序将崩溃,并显示 org.parceler.ParcelerRuntimeException: Unable to create ParcelableFactory for io.realm.FeedRealmProxy


5
现在有一个不同的解决方法:只需实现RealmModel接口,而不是继承自RealmObject
@RealmClass
public class User implements RealmModel {

}

你可以在Realm文档中找到更多信息。


但是使用Parcelable对象存储数据是一个好主意吗? - aleien
1
请参考以下答案:https://dev59.com/6Wox5IYBdhLWcg3w6oZf - Henrique de Sousa
链接无效,而且这个解决方法似乎没有起作用,为什么它被标记为答案?我将我的'RealmObject'更改为'RealmModel',但它仍然抱怨说它不可传递。 - behelit
链接已更新。关于执行“任何操作”,现在不再需要扩展对象并继承所有 Realm 方法,而是需要使用 RealmObject 的静态方法,例如 /* 使用 RealmModel 接口 */ RealmObject.isValid(p); 而不是 /* 使用 RealmObject 基类 */ p.isValid();。请参考更新后的文档以获取更多信息。 - Henrique de Sousa
@behelit 在立即投票反对一个回答之前,你可以多花点时间进行一些搜索努力,你同意吗? - Henrique de Sousa

1

目前无法在RealmObjects上实现Parcelable。 一个解决方案是使用两个realm文件:默认的作为对象存储,另一个专门用于旋转等临时保存。


0

Parceler在Android X中不起作用。 您可以使用以下内容:

class ExParcelable @JvmOverloads constructor(data: Any? = null) : Parcelable {
    var cls: String? = null
    var json: String? = null

    init {
        if (data is Parcel) {
            cls = data.readString()
            json = data.readString()
        } else {
            cls = data?.let { it::class.java }?.canonicalName
            json = Gson().toJson(data)
        }
    }

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(cls)
        parcel.writeString(json)
    }

    override fun describeContents(): Int {
        return 0
    }

    fun value(): Any? {
        return Gson().fromJson(this.json, Class.forName(this.cls))
    }

    companion object CREATOR : Creator<ExParcelable> {
        override fun createFromParcel(parcel: Parcel): ExParcelable {
            return ExParcelable(parcel)
        }

        override fun newArray(size: Int): Array<ExParcelable?> {
            return arrayOfNulls(size)
        }
    }
}

和:

inline fun <reified T : Any?> Intent.extra(key: String): T? {
    var value = extras?.get(key)
    if (value is ExParcelable) {
        value = value.value()
    } else if (T::class == Uri::class) {
        if (value is String) {
            value = value.toUri()
        }
    } else if (T::class == String::class) {
        if (value is Uri) {
            value = value.toString()
        }
    }
    return value as T?
}

inline fun <reified T : Any?> Intent.extra(key: String, value: T?) {
    when (value) {
        null -> {
            // no op
        }
        is Uri -> putExtra(key, value.toString())
        is Boolean -> putExtra(key, value)
        is BooleanArray -> putExtra(key, value)
        is Byte -> putExtra(key, value)
        is ByteArray -> putExtra(key, value)
        is Char -> putExtra(key, value)
        is CharArray -> putExtra(key, value)
        is Short -> putExtra(key, value)
        is ShortArray -> putExtra(key, value)
        is Int -> putExtra(key, value)
        is IntArray -> putExtra(key, value)
        is Long -> putExtra(key, value)
        is LongArray -> putExtra(key, value)
        is Float -> putExtra(key, value)
        is FloatArray -> putExtra(key, value)
        is Double -> putExtra(key, value)
        is DoubleArray -> putExtra(key, value)
        is Date -> putExtra(key, value)
        is Bundle -> putExtra(key, value)
        is Parcelable -> putExtra(key, value)
        is Serializable -> putExtra(key, value)
        is RealmObject -> putExtra(key, ExParcelable(value.get()))
        else -> putExtra(key, ExParcelable(value))
    }
}

并像这样使用它:

new Intent().apply{
    extra("test", realmObject)
}

和:

intent.extra("test")

0

Kotlin解决方案:

import io.realm.com_labtest_di_model_EntryRealmProxy
import org.parceler.Parcel


@RealmClass
@Parcel(implementations = arrayOf(com_labtest_di_model_EntryRealmProxy::class),
    value = org.parceler.Parcel.Serialization.BEAN,
    analyze = arrayOf(Movie::class))
open class Entry() : RealmObject() {
...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接