Использование LiveData с привязкой данных
При стабилизации компонентов Android Architecture я начал обновлять все основные базовые ViewModel
до новой реализации ViewModel
. По моему мнению, использование LiveData
рекомендуется удерживать класс Model
, поскольку он лучше справляется с жизненным циклом.
Мне нравится использовать Data Binding
, потому что он делает код более четким в Java/Kotlin, и нет необходимости "смотреть" изменения значений для обновления пользовательского интерфейса. Однако макет с использованием Data Binding
отслеживает только изменения данных, если Model
(или ViewModel) расширяет BaseObservable
и LiveData
не делает, Я понимаю, что одна из основных целей LiveData
должна соблюдаться и обновлять пользовательский интерфейс программно, но для простых обновлений Data Binding
очень полезен.
Эта проблема уже сообщалась (GitHub и Переполнение стека) и сначала было сказано, что версия 1.0 будет иметь его, и теперь говорят, что эта функция находится в разработке.
Чтобы использовать как LiveData
, так и Data Binding
, я создал очень простую реализацию класса, которая расширяет BaseObservable
:
import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MutableLiveData
import android.databinding.BaseObservable
class ObservableMutableLiveData<T>() : BaseObservable() {
private var data: MutableLiveData<T> = MutableLiveData()
constructor(data: T) : this() {
this.data.value = data
}
public fun set(value: T) {
if (value != data.value) {
data.value = value
notifyChange()
}
}
public fun get(): T? {
return data.value
}
public fun getObservable(): LiveData<T> {
return data
}
}
Итак, в основном мой ObservableMutableLiveData
является копией ObservableField
с помощью LiveData
для хранения модели и с этой реализацией макет обновления после каждого обновления модели.
Вопросы:
- Это плохая реализация
LiveData
? Разве эта оболочка "ломает" функциональные возможности LiveData
, например, с учетом жизненного цикла?
- В моем понимании
LiveData
- это новый ObservableField
. Правильно ли это?
Ответы
Ответ 1
Android Studio 3.1 (в настоящее время в Canary 6) устранит эту проблему, поскольку LiveData
может использоваться как observable field
:
Обновления привязки данных:
Теперь вы можете использовать объект LiveData в качестве наблюдаемого поля в выражениях привязки данных. Класс ViewDataBinding теперь включает новый метод setLifecycle, который вам нужно использовать для наблюдения за объектами LiveData.
Источник: Android Studio 3.1 Canary 6 теперь доступен
Ответ 2
Для тех, кто сталкивался с этим вопросом, ищет пример, как я, вот один:
В макете .xml
поместите элемент LiveData
с его типом:
<layout>
<data>
<variable
name="myString"
type="android.arch.lifecycle.MutableLiveData<String>"/>
</data>
...
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{myString}'
...
/>
...
</layout>
В вашем коде установите значение и владельца жизненного цикла:
MutableLiveData<String> myString = new MutableLiveData<>();
...
binding.setLifecycleOwner(this);
binding.setMyString(myString);
Вот оно :)
Обратите внимание, что значением по умолчанию для элементов LiveData
является null
, поэтому присвойте начальные значения, чтобы сразу получить желаемый эффект, или используйте этот для принудительной установки обнуляемости.
EDIT:
Используйте androidx.lifecycle.MutableLiveData<String>
как тип, если вы используете androidx
.
Ответ 3
Для androidx будет:
androidx.lifecycle.MutableLiveData
<layout>
<data>
<variable
name="myString"
type="androidx.lifecycle.MutableLiveData<String>"/>
</data>
...
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{myString}'
...
/>
...
</layout>
А для Котлина:
val myStr = MutableLiveData<String>()
...
binding.apply {
setLifecycleOwner(this)
this.myString = myStr
}
Удачи! :)