Наблюдаемость – это способность объекта уведомлять другие объекты об изменениях в своих данных. Библиотека привязки данных позволяет сделать объекты, поля или коллекции наблюдаемыми.
Для привязки данных можно использовать любой объект, но его изменение не приведет к автоматическому обновлению интерфейса. Привязка данных позволяет объектам данных уведомлять другие объекты (слушатели) об изменении данных. Существует три типа наблюдаемых классов: поля, коллекции и объекты.
Когда один из этих наблюдаемых объектов данных привязан к пользовательскому интерфейсу и свойство объекта данных изменяется, пользовательский интерфейс обновляется автоматически.
Поля, которые можно отслеживать
Если у ваших классов всего несколько свойств, возможно, не стоит создавать классы, реализующие интерфейс Observable. В этом случае вы можете использовать общий класс Observable и следующие классы для примитивов, чтобы сделать поля наблюдаемыми:
ObservableBooleanObservableByteObservableCharObservableShortObservableIntObservableLongObservableFloatObservableDoubleObservableParcelable
Отслеживаемые поля – это автономные отслеживаемые объекты, у которых есть одно поле. Примитивные версии позволяют избежать упаковки и распаковки во время операций доступа. Чтобы использовать этот механизм, создайте свойство public final на языке программирования Java или свойство только для чтения в Kotlin, как показано в следующем примере:
Kotlin
class User { val firstName = ObservableField<String>() val lastName = ObservableField<String>() val age = ObservableInt() }
Java
private static class User { public final ObservableField<String> firstName = new ObservableField<>(); public final ObservableField<String> lastName = new ObservableField<>(); public final ObservableInt age = new ObservableInt(); }
Чтобы получить доступ к значению поля, используйте методы доступа set() и get() или синтаксис свойств Kotlin:
Kotlin
user.firstName = "Google" val age = user.age
Java
user.firstName.set("Google"); int age = user.age.get();
Наблюдаемые коллекции
Некоторые приложения используют динамические структуры для хранения данных. Наблюдаемые коллекции позволяют
получать доступ к этим структурам с помощью ключа. Класс ObservableArrayMap полезен, когда ключ является ссылочным типом, например String, как показано в следующем примере:
Kotlin
ObservableArrayMap<String, Any>().apply { put("firstName", "Google") put("lastName", "Inc.") put("age", 17) }
Java
ObservableArrayMap<String, Object> user = new ObservableArrayMap<>(); user.put("firstName", "Google"); user.put("lastName", "Inc."); user.put("age", 17);
В макете вы можете найти карту, используя строковые ключи, как показано в следующем примере:
<data>
<import type="android.databinding.ObservableMap"/>
<variable name="user" type="ObservableMap<String, Object>"/>
</data>
…
<TextView
android:text="@{user.lastName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text="@{String.valueOf(1 + (Integer)user.age)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
Класс ObservableArrayList полезен, когда ключ является целым числом, как показано ниже:
Kotlin
ObservableArrayList<Any>().apply { add("Google") add("Inc.") add(17) }
Java
ObservableArrayList<Object> user = new ObservableArrayList<>(); user.add("Google"); user.add("Inc."); user.add(17);
В макете вы можете получить доступ к списку через индексы, как показано в следующем примере:
<data>
<import type="android.databinding.ObservableList"/>
<import type="com.example.my.app.Fields"/>
<variable name="user" type="ObservableList<Object>"/>
</data>
…
<TextView
android:text='@{user[Fields.LAST_NAME]}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
Наблюдаемые объекты
Класс, реализующий интерфейс Observable, позволяет регистрировать прослушиватели, которые должны получать уведомления об изменениях свойств наблюдаемого объекта.
В интерфейсе Observable есть механизм добавления и удаления прослушивателей, но вы сами решаете, когда отправлять уведомления. Чтобы упростить разработку, библиотека связывания данных предоставляет класс BaseObservable, который реализует механизм регистрации прослушивателя. Класс данных, реализующий BaseObservable, отвечает за уведомление об изменении свойств. Для этого назначьте аннотацию Bindable методу получения и вызовите метод notifyPropertyChanged() в методе установки, как показано в примере ниже.
Kotlin
class User : BaseObservable() { @get:Bindable var firstName: String = "" set(value) { field = value notifyPropertyChanged(BR.firstName) } @get:Bindable var lastName: String = "" set(value) { field = value notifyPropertyChanged(BR.lastName) } }
Java
private static class User extends BaseObservable { private String firstName; private String lastName; @Bindable public String getFirstName() { return this.firstName; } @Bindable public String getLastName() { return this.lastName; } public void setFirstName(String firstName) { this.firstName = firstName; notifyPropertyChanged(BR.firstName); } public void setLastName(String lastName) { this.lastName = lastName; notifyPropertyChanged(BR.lastName); } }
Привязка данных генерирует класс с именем BR в пакете модуля, который содержит идентификаторы ресурсов, используемых для привязки данных. Аннотация Bindable генерирует запись в файле класса BR во время компиляции. Если базовый класс для классов данных нельзя изменить, вы можете реализовать интерфейс Observable с помощью объекта PropertyChangeRegistry, чтобы эффективно регистрировать и уведомлять слушателей.
Объекты, учитывающие жизненный цикл
Макеты в приложении также можно привязать к источникам привязки данных, которые автоматически уведомляют интерфейс об изменениях в данных. Таким образом, ваши привязки будут учитывать жизненный цикл и срабатывать только тогда, когда пользовательский интерфейс виден на экране.
Привязка данных поддерживает StateFlow и LiveData. Подробнее о том, как использовать LiveData в привязке данных, рассказывается в статье Как использовать LiveData для уведомления UI об изменениях данных.
Используйте StateFlow
Если в вашем приложении используется Kotlin с сопрограммами, в качестве источника привязки данных можно использовать объекты StateFlow. Чтобы использовать объект StateFlow с классом привязки, укажите владельца жизненного цикла, который будет определять область действия объекта StateFlow. В следующем примере действие указывается как владелец жизненного цикла после создания экземпляра класса привязки:
class ViewModelActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Inflate view and obtain an instance of the binding class.
val binding: UserBinding = DataBindingUtil.setContentView(this, R.layout.user)
// Specify the current activity as the lifecycle owner.
binding.lifecycleOwner = this
}
}
Как описано в статье Привязка представлений макета к компонентам архитектуры, привязка данных без проблем работает с объектами ViewModel. Вы можете использовать StateFlow и ViewModel вместе, как показано ниже.
class ScheduleViewModel : ViewModel() {
private val _username = MutableStateFlow<String>("")
val username: StateFlow<String> = _username
init {
viewModelScope.launch {
_username.value = Repository.loadUserName()
}
}
}
В макете назначьте свойства и методы объекта ViewModel соответствующим представлениям, используя выражения привязки, как показано в следующем примере:
<TextView
android:id="@+id/name"
android:text="@{viewmodel.username}" />
Интерфейс автоматически обновляется при изменении значения имени пользователя.
Отключить поддержку StateFlow
В приложениях, использующих Kotlin и AndroidX, поддержка StateFlow автоматически включается вместе с привязкой данных. Это означает, что зависимость сопрограмм автоматически включается в ваше приложение, если она ещё не доступна.
Чтобы отключить эту функцию, добавьте в файл build.gradle следующий код:
Яркий
android { ... dataBinding { addKtx = false } }
Kotlin
android { ... dataBinding { addKtx = false } }
Вы также можете отключить StateFlow для всего проекта, добавив в файл gradle.properties следующую строку:
Яркий
android.defaults.databinding.addKtx = false
Kotlin
android.defaults.databinding.addKtx = false
Дополнительные ресурсы
Дополнительную информацию о привязке данных можно найти в следующих ресурсах:
Образцы
Практические работы
Записи в блоге
Рекомендуем
- Примечание. Текст ссылки показывается, когда JavaScript отключен.
- Модуль Saved State для ViewModel
- Как связать макеты с компонентами архитектуры
- Обзор библиотеки Paging