Наблюдаемость означает способность объекта уведомлять других об изменениях в его данных. Библиотека привязки данных позволяет сделать объекты, поля или коллекции наблюдаемыми.
Вы можете использовать любой объект для привязки данных, но изменение объекта не приводит к автоматическому обновлению пользовательского интерфейса. Вы можете использовать привязку данных, чтобы дать вашим объектам данных возможность уведомлять другие объекты (так называемые прослушиватели) при изменении их данных. Существует три типа наблюдаемых классов: поля , коллекции и объекты .
Когда один из этих наблюдаемых объектов данных привязан к пользовательскому интерфейсу и свойство объекта данных изменяется, пользовательский интерфейс обновляется автоматически.
Наблюдаемые поля
Если ваши классы имеют всего несколько свойств, возможно, не стоит создавать классы, реализующие интерфейс Observable
. В этом случае вы можете использовать общий класс Observable
и следующие классы, специфичные для примитивов, чтобы сделать поля наблюдаемыми:
-
ObservableBoolean
-
ObservableByte
-
ObservableChar
-
ObservableShort
-
ObservableInt
-
ObservableLong
-
ObservableFloat
-
ObservableDouble
-
ObservableParcelable
Наблюдаемые поля — это автономные наблюдаемые объекты, имеющие одно поле. Примитивные версии избегают упаковки и распаковки во время операций доступа. Чтобы использовать этот механизм, создайте public final
на языке программирования Java или свойство только для чтения в Kotlin, как показано в следующем примере:
Котлин
class User { val firstName = ObservableField<String>() val lastName = ObservableField<String>() val age = ObservableInt() }
Ява
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 :
Котлин
user.firstName = "Google" val age = user.age
Ява
user.firstName.set("Google"); int age = user.age.get();
Наблюдаемые коллекции
Некоторые приложения используют динамические структуры для хранения данных. Наблюдаемые коллекции позволяют получить доступ к этим структурам с помощью ключа. Класс ObservableArrayMap
полезен, когда ключ имеет ссылочный тип, например String
, как показано в следующем примере:
Котлин
ObservableArrayMap<String, Any>().apply { put("firstName", "Google") put("lastName", "Inc.") put("age", 17) }
Ява
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
полезен, когда ключ является целым числом, а именно:
Котлин
ObservableArrayList<Any>().apply { add("Google") add("Inc.") add(17) }
Ява
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()
в установщике, как показано в следующем примере:
Котлин
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) } }
Ява
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 для уведомления пользовательского интерфейса об изменениях данных .
Используйте 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 } }
Котлин
android { ... dataBinding { addKtx = false } }
Альтернативно вы можете отключить StateFlow
глобально в своем проекте, добавив следующую строку в файл gradle.properties
:
классный
android.defaults.databinding.addKtx = false
Котлин
android.defaults.databinding.addKtx = false
Дополнительные ресурсы
Чтобы узнать больше о привязке данных, см. следующие дополнительные ресурсы:
Образцы
Кодлабы
Сообщения в блоге
{% дословно %}Рекомендуется для вас
- Примечание: текст ссылки отображается, когда JavaScript отключен.
- Модуль сохраненного состояния для ViewModel
- Привязка видов компоновки к компонентам архитектуры
- Обзор библиотеки подкачки