Почему существует отдельный подкласс MutableLiveData LiveData?

Похоже, что MutableLiveData отличается от LiveData только создавая setValue() и postValue(), тогда как в LiveData они защищены.

Каковы некоторые причины сделать отдельный класс для этого изменения, а не просто определять эти методы как общедоступные в самой LiveData?

Вообще говоря, такая форма наследования (повышение видимости определенных методов является единственным изменением) хорошо известной практикой и каковы некоторые сценарии, где это может быть полезно (если у нас есть доступ ко всему коду)?

Ответ 1

В LiveData - Документация разработчика для Android вы можете видеть, что для LiveData setValue() и postValue() не являются общедоступными.

Принимая во внимание, что в MutableLiveData - Документация разработчика для Android вы можете видеть, что MutableLiveData расширяет LiveData внутренне, а также два волшебных метода LiveData являются общедоступными в этом, и они являются setValue() и postValue().

setValue(): установить значение и отправить значение всем активным наблюдателям, необходимо вызвать из основного потока.

postValue(): отправить задачу в основной поток, чтобы переопределить значение, заданное setValue(), должно вызываться из фонового потока.

Таким образом, LiveData является неизменным. MutableLiveData является LiveData, который является изменяемым и потокобезопасна.

Ответ 2

Это весь файл MutableLiveData.java:

package androidx.lifecycle;
/**
 * {@link LiveData} which publicly exposes {@link #setValue(T)} and {@link #postValue(T)} method.
 *
 * @param <T> The type of data hold by this instance
*/
@SuppressWarnings("WeakerAccess")
public class MutableLiveData<T> extends LiveData<T> {
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }
    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

Так что да, разница достигается только за счет postValue и setValue.

Один случай использования, который я могу вспомнить из своей головы, - это инкапсуляция с использованием Backing Property в Kotlin. Вы можете открыть LiveData для своего фрагмента/действия (UI Controller), даже если у вас есть MutableLiveData для манипуляций в вашем классе ViewModel.

    class TempViewModel : ViewModel() {
        ...
        private val _count = MutableLiveData<Int>()
        val count: LiveData<Int>
            get() = _count
        public fun incrementCount() = _score.value?.plus(1)
        ...
    }

Таким образом, ваш контроллер пользовательского интерфейса сможет наблюдать значения только без возможности их редактирования. Очевидно, что ваш контроллер пользовательского интерфейса может редактировать значения с помощью открытых методов TempViewModel таких как incrementCount().

Примечание: чтобы прояснить изменчивую/неизменную путаницу -

data class User(var name: String, var age: Int)

class DemoLiveData: LiveData<User>()

var demoLiveData: LiveData<User>? = DemoLiveData()

fun main() {
    demoLiveData?.value = User("Name", 23) // ERROR
    demoLiveData?.value?.name = "Name" // NO ERROR
    demoLiveData?.value?.age = 23  // NO ERROR
}