Почему существует отдельный подкласс 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
}