MediatorLiveDarta can act as a middleman to listen to other LiveData. For example, if you want to display the number of words while entering text in ExitText, the MediatorLiveDarta can act as a middleman to listen to other LiveData

class MainViewModel : ViewModel() {
    val message: MutableLiveData<String> = MutableLiveData()
    val count: MediatorLiveData<Int> = MediatorLiveData()

    init {
        count.value = 0

        count.addSource(message) {
            valcnt = message.value? .length ? :0
            count.postValue(cnt)
        }
    }

    fun postMessage(message: String) {
        this.message.postValue(message)
    }
}
Copy the code

The EditText callback updates the message with postMessage, and the count updates itself by listening for changes to the message with addSource

addSource

If the given LiveData is already added as a source but with a different Observer, IllegalArgumentException will be thrown.

AddSource can ensure that monitored Livedata will not be subscribed twice. If we observe manually, it may cause data acceptance exceptions due to repeated subscriptions. This can be clearly seen from the addSrouce source code

public <S> void addSource(@NonNull LiveData<S> source, @NonNullObserver<S> onChanged) { Source<S> e = new Source<>(source, onChanged); Source<? > existing = mSources.putIfAbsent(source, e);if(existing ! =null&& existing.mObserver ! = onChanged) {throw new IllegalArgumentException(
                    "This source was already added with the different observer");
        }
        if(existing ! =null) {
            return;
        }
        if(hasActiveObservers()) { e.plug(); }}Copy the code

Note the use of postValue

In the example above, would it work if we changed the code to the implementation?

class MainViewModel : ViewModel() {
    val message: MutableLiveData<String> = MutableLiveData()
    val count: MutableLiveData<Int> = MutableLiveData()

    fun postMessage(message: String) {
        this.message.postValue(message)
        updateCount()
    }

    private fun updateCount(a) {
        valcnt = message.value? .length ? :0
        count.postValue(cnt)
    }
}
Copy the code

After testing, it was found that count and message updates were out of sync. Because postValue is an asynchronous operation, after updating message via postValue, we may obtain the latest value of message in updateCount, which may cause a bug.

The last

In simple code, such a bug is easy to detect, but in a complex project, timing issues like this can easily be ignored when writing code, so when using LiveData, use tools like MediatorLiveData, even if you write two more lines of code, to ensure that the timing is accurate.