【问题标题】:RealmObject AND ParcelableRealmObject 和 Parcelable
【发布时间】:2014-12-01 15:05:38
【问题描述】:

我是 Android 版 Realm 的新手,所以我不确定我是否以正确的方式处理这个问题。我有一个看起来像这样的类:

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

问题是Parcelable 接口包含describeContents() writeToParcel() 之类的方法,而RealmObjects 不应该具有除getter 和setter 之外的方法:

Error:(81, 17) error: Only getters and setters should be defined in model classes

所以我的问题是:我怎样才能让这两者一起工作?有没有比创建一个单独的类更好的方法(可能像RealmEntry)?这样做会导致大量重复代码...

【问题讨论】:

  • 你为什么要尝试使用 Parcelable 对象和领域?
  • 好吧,我使用 Pareclable 在配置更改(设备旋转)时保留对象,并使用 Realm 将对象存储到数据库中
  • 在配置更改后重新查询数据库不是更有意义吗?考虑到您使用的是带有缓存机制的 RealmDB,这可能会更快。

标签: java android sqlite parcelable realm


【解决方案1】:

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


实际上,有一个解决方法。如果您愿意使用第三方库(Parceler)进行Parcelable 生成,您可以获得您想要的结果。请参阅my answer to this other question,为方便起见,请在下面引用。

使用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 而崩溃。

【讨论】:

    【解决方案2】:

    现在有一个不同的解决方法:只需实现RealmModel 接口,而不是从RealmObject 扩展:

    @RealmClass
    public class User implements RealmModel {
    
    }
    

    您可以在Realm Documentation找到更多信息。

    【讨论】:

    【解决方案3】:

    目前无法在 RealmObjects 上实现 Parcelable。 一种解决方案是使用两个领域文件:默认一个作为对象存储,一个专门用于临时保存以进行轮换等。

    【讨论】:

      【解决方案4】:

      使用 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() {
      ...
      

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-07-27
          • 2018-09-13
          • 2012-03-08
          • 1970-01-01
          • 2017-02-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多