Convert LiveData to MutableLiveData

A Kotlin extension to trasform LiveData into MutableLiveData:

/**
 * 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
}

If you really need to, then you can use the mediator trick.

In your ViewModel

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

 init {
      mediator.addSource(sourceProduct, { product.value = it })
 }

In fragment/activity

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

Since Room doesn't support MutableLiveData and has support for LiveData only, your approach of creating a wrapper is the best approach I can think of. It will be complicated for Google to support MutableLiveDatasince the setValue and postValue methods are public. Where as for LiveData they are protected which gives more control.


Call me crazy but AFAIK there is zero reason to use a MutableLiveData for the object that you received from the DAO.

The idea is that you can expose an object via LiveData<List<T>>

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

Now you can observe them:

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;
});

So if you want to make this live data "emit a new data and modify it", then you need to insert the profile into the database. The write will re-evaluate this query and it will be emitted once the new profile value is written to db.

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

So there is no reason to use getValue/setValue, just write to your db.