Обертывание MutableList в LiveData или MutableLiveData
Каковы рекомендуемые способы обертывания MutableList
в любом LiveData
или же MutableLiveData
так, что можно изменить список и наблюдать за изменениями, которые он претерпевает?
У меня есть несколько довольно коротких таблиц (<20 элементов) в комнате (он кэширует значения, полученные с сервера). Я хотел бы сохранить изменяемое подмножество этих элементов; для использования в качестве фильтров в запросах к другим, более крупным таблицам. Я думал назначить MutableList
к классу модели в моем приложении и сделать его видимым, оборачивая этот класс либо в MutableLiveData
или же LiveData
, Затем, обновляя элементы в этих выборках, я мог запускать необходимые запросы для больших таблиц.
В настоящее время мой код имеет следующую структуру, я сократил ее в своем вопросе до того, что я считаю актуальным. В конце концов я хотел бы использовать несколько keyset
в более сложных запросах. Мой упрощенный файл модели выглядит следующим образом:
class Model(application : Application) : AndroidViewModel(application)
{
val keys : LiveData<List<Key>>
val keyset : LiveData<MutableList<Key>>
val values : LiveData<List<Value>>
init {
keys = repository.keys
values = repository.values
keyset = mutableListOf<Key>() // I'm not entirely sure how to instantiate LiveData<MutableList<Key>>
}
}
это зависит от хранилища,
class Repository(private val queryset : QuerySet)
{
val keys : LiveData<List<Key>> = queryset.getKeys()
val values : LiveData<List<Value>> = queryset.getValues()
}
Который опирается на набор запросов
@Dao
class QuerySet(application : Application) : AndroidViewModel(application)
{
@Query("SELECT * FROM KeyEntity")
fun getKeys() : LiveData<list<Key>>
@Query("SELECT * FROM ValueEntity WHERE key in (:keys)")
fun getValues(keys : MutableList<Key>) : LiveData<list<Value>>
}
Key
а также Value
классы просто POJO для KeyEntity
а также ValueEntity
и просто укажите те же поля.
Должен ли я использовать MutableLiveData
или же LiveData
для этого? Если так, то как следует реализовать keyset
? Возможно, есть более канонический способ сделать это?
2 ответа
LiveData против MutableLiveData
Я не был уверен, должен ли я был обернуть MutableList
как LiveData<MutablList<POJO>>
или как MutableLiveData<MutableList<POJO>>
, где POJO
является экземпляром объекта базы данных или класса данных, проксирующим один или несколько объектов базы данных. Снех Пандая кратко объясняет разницу между двумя классами. Я также не был уверен, как их создать. Следующее создает экземпляр, но value
из keyset
инициализируется как null
и нужно установить начальное значение для MutableLiveData
,
class Model(application : Application) : AndroidViewModel(application)
{ ...
val keyset : LiveData<MutableList<Key>>
init { ...
keyset = MutableLiveData<MutableList<Key>>() // Initialized as null
keyset.value = mutableListOf<Key>() // Assign an empty list
... }
... }
Есть нюанс в MutableLiveData
формально не инкапсулирует данные. То есть, когда он оборачивает элемент, он не отображает методы обернутых элементов, поскольку он сам отправляет уведомления об изменении обернутого элемента. Он просто отслеживает, когда обернутый предмет был заменен (см. Gznlt). Samnang CHEA предоставляет хороший метод для поддержки этого.
Местоположение, местоположение, местоположение, ...
Я не был уверен, где формально разместить keyset
приписывать. Документация Android предоставляет следующую информацию; как оказалось, я был на правильном пути.
Обновить объекты LiveData
LiveData не имеет общедоступных методов для обновления сохраненных данных. Класс MutableLiveData публично предоставляет методы setValue(T) и postValue(T), и вы должны использовать их, если вам нужно отредактировать значение, хранящееся в объекте LiveData. Обычно MutableLiveData используется в ViewModel, а затем ViewModel предоставляет неизменные объекты LiveData только наблюдателям.
Запросы
То, что я еще не разработал, это как запустить обновление values
,
Наблюдатель уведомляется только об изменениях значения LiveData.
Это справедливо как для LiveData, так и для StateFlow.
Когда вы объявляете экземпляр
MutableLiveData<MutableList<Any>>
, а затем вы добавляете значение в список, обернутый внутри MutableLiveData, как
variable.value.add(Any)
, наблюдатель не будет уведомлен. Он не прослушивает такие изменения, когда обновляется внутреннее содержимое списка/модели.
Существуют различные обходные пути, позволяющие уведомить наблюдателя путем создания расширений, но это довольно сложно для выполнения простейшей задачи.
Самый простой способ заключается в следующем:
private val _mobileTopUp = MutableList<List<DataModel>>(emptyList())
Затем создайте простой изменяемый список, в котором вы будете собирать элементы. Вы можете объявить этот список поверх вашей функции, чтобы он становился пустым каждый раз, когда вы вызываете функцию, чтобы избежать избыточных данных или нет. Это полностью зависит от вас
val list = mutableListOf<DataModel>()
list.add(it)
_mobileTopUp.value = list
Теперь наблюдатель будет уведомлен, потому что здесь мы устанавливаем list как значение LiveData.