web-dev-qa-db-ja.com

LiveDataをMutableLiveDataに変換する

どうやら、RoomはMutableLiveDataを処理できず、次のエラーを返すため、LiveDataに固執する必要があります。

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

この方法で、DBヘルパーに「カスタム」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()を呼び出し、動作しません。

誰かがこれに対する解決策を見つけましたか?

7
kike

クレイジーと呼んでくださいが、DAOから受け取ったオブジェクトにMutableLiveDataを使用する理由はありません。

アイデアは、LiveData<List<T>>を介してオブジェクトを公開できるということです。

@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を使用する理由はなく、データベースに書き込むだけです。

9
EpicPandaForce

リポジトリでLiveDataを取得し、MutableLivedataに変換できます。

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

RoomはMutableLiveDataをサポートせず、LiveDataのみをサポートしているため、ラッパーを作成するアプローチは、私が考えることができる最良のアプローチです。 GoogleメソッドとMutableLiveDataメソッドはsetValueであるため、postValuepublicをサポートするのは複雑になります。 LiveDataprotectedであり、より多くの制御が可能です。

1
Sagar

本当に必要な場合は、メディエータートリックを使用できます。

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 })
1
Zakhar Rodionov