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

Это выглядит как MutableLiveData отличается от LiveData только сделав setValue() а также postValue() методы публичные, тогда как в LiveData они защищены.

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

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

4 ответа

Решение

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

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

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

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

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

Это все 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-контроллер), даже если у вас может быть MutableLiveData для манипуляций в вашем ViewModel учебный класс.

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

Таким образом, ваш UI-контроллер сможет только наблюдать значения, не имея возможности их редактировать. Очевидно, ваш UI-контроллер может редактировать значения, используя общедоступные методы 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
}

MutableLiveData расширяется от LiveData. К защищенным методам LiveData можно обращаться только самостоятельно или подклассами. Таким образом, в этом случае MutableLiveData, являющийся подклассом LiveData, может получить доступ к этим защищенным методам.

Что вы хотите сделать, так это наблюдать за экземпляром и посмотреть, есть ли какие-либо изменения. Но в то же время вы не хотите, чтобы "посторонние" изменили тот случай, за которым вы наблюдаете. В некотором смысле это создает проблему, так как вы хотели бы иметь объект, который можно изменять, обновлять любой новый статус, а не изменять, чтобы убедиться, что никто, кто не должен, не может обновлять этот экземпляр. Эти две функции конфликтуют друг с другом, но их можно решить, создав дополнительный слой.

Итак, что вы делаете, так это расширяете свой класс LiveData с помощью класса, который может получить доступ к его методам. Подуровень, в данном случае MutableLiveData, может получить доступ к защищенным методам своего родителя (/super).

Теперь вы начинаете создавать экземпляры и создаете свой экземпляр наблюдателя MutableLiveData. В то же время вы создаете экземпляр LiveData, ссылающийся на этот же экземпляр. Поскольку MutableLiveData расширяет LiveData, любой экземпляр MutableLiveData является объектом LiveData и, следовательно, на него может ссылаться переменная LiveData.

Теперь фокус почти готов. Вы предоставляете только экземпляр LiveData, никто не может использовать его защищенные методы и не может преобразовать его в super (возможно, во время компиляции, но он не будет работать: ошибка RunTime). И вы сохраняете фактический экземпляр подкласса закрытым, поэтому его могут изменить только те, кто владеет экземпляром, используя методы экземпляра.

//create instance of the sub class and keep this private
private val _name: MutableLiveData<String> = MutableLiveData<String>()
//create an instance of the super class referring to the same instance
val name: LiveData<String> = _name
//assign observer to the super class, being unable to change it
name.value.observe(.....)

Теперь суперкласс уведомляет о любых изменениях.

//change the instance by using the sub class
_name.postValue(...)
//or _name.setValue(...)

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

Да, это хорошо известно, и описанный выше сценарий является обычным. Удалите шаблон наблюдателя и просто сделайте его в форме set/get, и это принесет не меньшую пользу. В зависимости от того, где вы это реализуете, в конце концов не будет золотых правил.

LiveData и MutableLiveData — это два класса в Android Jetpack, которые используются для управления данными с учетом жизненного цикла. Они оба наблюдаемы, что означает, что их можно прослушивать на предмет изменений в их данных. Однако между этими двумя классами есть некоторые ключевые различия:

LiveData является неизменяемым. Это означает, что значение объекта LiveData нельзя изменить напрямую. Вместо этого вам необходимо создать новый объект LiveData с новым значением. Это помогает предотвратить повреждение данных и упрощает оценку состояния вашего приложения.MutableLiveData является изменяемым. Это означает, что значение объекта MutableLiveData можно изменить напрямую. Это может быть полезно в случаях, когда вам необходимо обновить данные в ответ на ввод пользователя или другие события. Однако важно использовать MutableLiveData осторожно, поскольку при неправильном использовании это может привести к повреждению данных. В общем, вам следует использовать LiveData, если вы хотите создать неизменяемый источник данных. Это наиболее распространенный вариант использования LiveData. Вам следует использовать MutableLiveData, когда вам нужно иметь возможность изменять данные напрямую. Это менее распространено, но в некоторых случаях может быть полезно. Автоматическое управление жизненным циклом Да Да Варианты использования Создание неизменяемого источника данных Непосредственное обновление данных Надеюсь, это поможет! Дайте мне знать, если у вас есть еще вопросы

Другие вопросы по тегам