将LiveData转换为MutableLiveData

kik*_*ike 8 android kotlin android-room android-livedata android-architecture-components

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

error: Not sure how to convert a Cursor to this method's return type
Run Code Online (Sandbox Code Playgroud)

我用这种方式在我的数据库助手中创建了一个"自定义"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()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,我从DB获取更新并可以保存Profile对象,但我无法修改属性.

例如: mutableLiveData.value = Profile()会工作. mutableLiveData.value.userName = "name"会打电话getValue()postValue()不会工作.

有没有人为此找到解决方案?

Epi*_*rce 9

叫我疯了,但AFAIK没有理由将MutableLiveData用于从DAO收到的对象.

这个想法是你可以通过暴露对象 LiveData<List<T>>

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

现在你可以观察它们:

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;
});
Run Code Online (Sandbox Code Playgroud)

因此,如果要使此实时数据"发出新数据并对其进行修改",则需要将配置文件插入数据库.write将重新评估此查询,并在将新的配置文件值写入db后将其发出.

dao.insert(profile); // this will make LiveData emit again
Run Code Online (Sandbox Code Playgroud)

所以没有理由使用getValue/ setValue,只是写入你的数据库.

  • 当您从数据库中独立修改对象,然后从网络中获取对象,保存到数据库,然后您有一个"来自网络的新状态"和一个本地修改的对象时会发生什么? (2认同)

Zak*_*nov 9

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

在您的视图模型中

 val sourceProduct: LiveData<Product>() = repository.productFromDao()
 val product = MutableLiveData<Product>()

 val mediator = MediatorLiveData<Unit>()

 init {
      mediator.addSource(sourceProduct, { product.value = it })
 }
Run Code Online (Sandbox Code Playgroud)

在片段/活动中

observe(mediator, {})
observe(product, { //handle product })
Run Code Online (Sandbox Code Playgroud)


小智 5

Kotlin 扩展可转换LiveDataMutableLiveData

/**
 * 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
}
Run Code Online (Sandbox Code Playgroud)