【问题标题】:Convert LiveData to MutableLiveData将 LiveData 转换为 MutableLiveData
【发布时间】:2018-11-29 07:59:55
【问题描述】:

显然,Room 无法处理 MutableLiveData,我们必须坚持使用 LiveData,因为它返回以下错误:

error: Not sure how to convert a Cursor to this method's return type

我以这种方式在我的数据库助手中创建了一个“自定义”MutableLiveData:

class ProfileRepository @Inject internal constructor(private val profileDao: ProfileDao): ProfileRepo{

    override fun insertProfile(profile: Profile){
        profileDao.insertProfile(profile)
    }

    val mutableLiveData by lazy { MutableProfileLiveData() }
    override fun loadMutableProfileLiveData(): MutableLiveData<Profile> = mutableLiveData

    inner class MutableProfileLiveData: MutableLiveData<Profile>(){

        override fun postValue(value: Profile?) {
            value?.let { insertProfile(it) }
            super.postValue(value)
        }

        override fun setValue(value: Profile?) {
            value?.let { insertProfile(it) }
            super.setValue(value)
        }

        override fun getValue(): Profile? {
            return profileDao.loadProfileLiveData().getValue()
        }
    }
}

这样,我从 DB 获取更新,可以保存 Profile 对象,但我不能修改属性。

例如: mutableLiveData.value = Profile() 会工作。 mutableLiveData.value.userName = "name" 会调用 getValue() 而不是 postValue() 并且不会工作。

有人找到解决办法了吗?

【问题讨论】:

    标签: android kotlin android-room android-architecture-components android-livedata


    【解决方案1】:

    说我疯了,但 AFAIK 没有理由为您从 DAO 收到的对象使用 MutableLiveData。

    这个想法是你可以通过LiveData&lt;List&lt;T&gt;&gt;公开一个对象

    @Dao
    public interface ProfileDao {
        @Query("SELECT * FROM PROFILE")
        LiveData<List<Profile>> getProfiles();
    }
    

    现在你可以观察它们了:

    profilesLiveData.observe(this, (profiles) -> {
        if(profiles == null) return;
    
        // you now have access to profiles, can even save them to the side and stuff
        this.profiles = profiles;
    });
    

    因此,如果您想让这些实时数据“发出新数据并对其进行修改”,则需要将配置文件插入数据库。写入将重新评估此查询,并在新的配置文件值写入 db 后发出。

    dao.insert(profile); // this will make LiveData emit again
    

    所以没有理由使用getValue/setValue,只需写入您的数据库即可。

    【讨论】:

    • 我明白你的意思。现在的解决方案与拥有 LiveData 对象并保存在数据库中没有区别。这里的想法是能够独立修改数据库中的一些属性。
    • 当您独立于数据库修改对象,然后从网络获取对象,保存到数据库时会发生什么,现在您有一个“来自网络的新状态”和一个对象是本地修改的吗?
    • @EpicPandaForce 面临类似问题的 db 更新未反映在实时数据上。这就是为什么我试图发布到可变的实时数据对象
    • 如果你通过 DAO 插入 DB,那么如果 LiveData&lt;List&lt;T&gt;&gt; 从 DAO 暴露并且你观察它,那么你收到新数据。
    【解决方案2】:

    如果你真的需要,那么你可以使用中介技巧。

    在您的 ViewModel 中

     val sourceProduct: LiveData<Product>() = repository.productFromDao()
     val product = MutableLiveData<Product>()
        
     val mediator = MediatorLiveData<Unit>()
    
     init {
          mediator.addSource(sourceProduct, { product.value = it })
     }
    

    在片段/活动中

    observe(mediator, {})
    observe(product, { /* handle product */ })
    

    【讨论】:

    • 使用这种技术,对源产品的任何更改都会在中介 livedata 中自动触发?因此我只需要观察产品还是我需要同时观察产品和中介的实时数据?
    • @Kolaaa 是正确的 - 你只需要观察中介 livedata
    【解决方案3】:

    由于 Room 不支持 MutableLiveData 并且仅支持 LiveData,因此您创建包装器的方法是我能想到的最佳方法。 Google 支持 MutableLiveData 会很复杂,因为 setValuepostValue 方法是 public。至于LiveData,它们是protected,这提供了更多控制权。

    【讨论】:

      【解决方案4】:

      LiveData 转换为MutableLiveData 的Kotlin 扩展:

      /**
       * Transforms a [LiveData] into [MutableLiveData]
       *
       * @param T type
       * @return [MutableLiveData] emitting the same values
       */
      fun <T> LiveData<T>.toMutableLiveData(): MutableLiveData<T> {
          val mediatorLiveData = MediatorLiveData<T>()
          mediatorLiveData.addSource(this) {
              mediatorLiveData.value = it
          }
          return mediatorLiveData
      }
      

      【讨论】:

        【解决方案5】:

        在您的存储库中,您可以获得LiveData 并将其转换为MutableLivedata

        var data= dao.getAsLiveData()
        return MutableLiveData<T>(data.value)
        

        【讨论】:

        • 这是错误的方式,目前没有人保证livedata中有数据。
        • 如果我们之前检查 null 怎么办?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多