Why There's a Separate Mutablelivedata Subclass of Livedata

Why there's a separate MutableLiveData subclass of LiveData?

In LiveData - Android Developer Documentation, you can see that for LiveData, setValue() & postValue() methods are not public.

Whereas, in MutableLiveData - Android Developer Documentation, you can see that, MutableLiveData extends LiveData internally and also the two magic methods of LiveData is publicly available in this and they are setValue() & postValue().

setValue(): set the value and dispatch the value to all the active observers, must be called from main thread.

postValue() : post a task to main thread to override value set by setValue(), must be called from background thread.

So, LiveData is immutable. MutableLiveData is LiveData which is mutable & thread-safe.

When to use MutableLiveData and LiveData

LiveData has no public method to modify its data.

LiveData<User> getUser() {
if (userMutableLiveData == null) {
userMutableLiveData = new MutableLiveData<>();
}
return userMutableLiveData
}

You can't update its value like getUser().setValue(userObject) or getUser().postValue(userObject)

So when you don't want your data to be modified use LiveData
If you want to modify your data later use MutableLiveData

Why are MutableLiveData variables declared with equals sign (=)?

Kotlin auto detects the type, so you do not need to specify it. These are equivalent

val foo: Int = 123
val foo = 123

However, if you have a variable that is initialized later, you must provide the type, as otherwise the compiler can't determine what type it is. For instance,

class MyClass {
val foo: Int // must specify type

init {
foo = /* compute foo */
}
}

It has nothing to do with LiveData or MutableLiveData.

LiveData works with recyle view but MutableLiveData don't. Why?

Try MediatorLiveData instead of mutable

Repository:

class TipRepository (private val tipDAO: TipDAO){

// Room executes all queries on a separate thread.
// Observed LiveData will notify the observer when the data has changed.
val allTips: LiveData<List<Tip>> = tipDAO.getAll()

// The suspend modifier tells the compiler that this must be called from a
// coroutine or another suspend function.

suspend fun insert (tip: Tip){
tipDAO.insert(tip)
}

fun getAlphabetizedTips (): LiveData<List<Tip>> {
return tipDAO.getAlphabetizedTips()
}

suspend fun delete (tip: Tip) {
tipDAO.delete(tip)
}

Model view

class TipViewModel (application: Application): AndroidViewModel (application) {

private val repository : TipRepository
val allTips = MediatorLiveData<List<Tip>()

init {
val tipDAO = TipRoomDatabase.getDatabase(application).tipDao()
repository = TipRepository(tipDAO)
allTips.addSource(repository.allTips){
this.allTips.value = it
}
}

Convert LiveData to MutableLiveData

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.



Related Topics



Leave a reply



Submit