Библиотека привязки данных генерирует классы привязки, которые можно использовать для доступа к переменным и представлениям макета. В этой документации показано, как создавать и настраивать сгенерированные классы привязки.
Сгенерированный класс привязки связывает переменные макета с представлениями в макете. Вы можете настроить название и пакет привязки. Все сгенерированные классы привязки наследуют класс ViewDataBinding.
Для каждого файла макета создается класс привязки. По умолчанию название класса – это название файла макета, преобразованное в стиль PascalCase с добавлением суффикса Binding. Например, если название файла макета — activity_main.xml, то соответствующий сгенерированный класс будет называться ActivityMainBinding.
Этот класс содержит все привязки свойств макета к представлениям макета и знает, как присваивать значения выражениям привязки.
Создание объекта привязки
Объект привязки создается сразу после заполнения макета, чтобы иерархия View не была изменена до привязки к View с выражениями в макете. Самый распространенный способ привязать объект к макету – использовать статические методы в классе привязки. Вы можете развернуть иерархию View и связать с ней объект, используя метод inflate() класса связывания, как показано в следующем примере:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val binding: MyLayoutBinding = MyLayoutBinding.inflate(layoutInflater) setContentView(binding.root) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MyLayoutBinding binding = MyLayoutBinding.inflate(getLayoutInflater()); setContentView(binding.root); }
Существует альтернативная версия метода inflate(), которая принимает объект ViewGroup в дополнение к объекту LayoutInflater, как показано в примере ниже.
Kotlin
val binding: MyLayoutBinding = MyLayoutBinding.inflate(getLayoutInflater(), viewGroup, false)
Java
MyLayoutBinding binding = MyLayoutBinding.inflate(getLayoutInflater(), viewGroup, false);
Если макет заполняется с помощью другого механизма, вы можете привязать его отдельно, как показано ниже.
Kotlin
val binding: MyLayoutBinding = MyLayoutBinding.bind(viewRoot)
Java
MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);
Иногда тип привязки неизвестен заранее. В таких случаях вы можете создать привязку с помощью класса DataBindingUtil, как показано в следующем фрагменте кода:
Kotlin
val viewRoot = LayoutInflater.from(this).inflate(layoutId, parent, attachToParent) val binding: ViewDataBinding? = DataBindingUtil.bind(viewRoot)
Java
View viewRoot = LayoutInflater.from(this).inflate(layoutId, parent, attachToParent); ViewDataBinding binding = DataBindingUtil.bind(viewRoot);
Если вы используете элементы привязки данных в адаптере Fragment, ListView или RecyclerView, то можете использовать методы inflate() классов привязки или класс DataBindingUtil, как показано в примере кода ниже.
Kotlin
val listItemBinding = ListItemBinding.inflate(layoutInflater, viewGroup, false) // or val listItemBinding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false)
Java
ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false); // or ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);
Представления с идентификаторами
Библиотека привязки данных создает неизменяемое поле в классе привязки для каждого представления, у которого есть идентификатор в макете. Например, библиотека привязки данных создает поля firstName и lastName типа TextView из следующего макета:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type="com.example.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}"
android:id="@+id/firstName"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.lastName}"
android:id="@+id/lastName"/>
</LinearLayout>
</layout>
Библиотека извлекает представления, включая идентификаторы, из иерархии представлений за один проход. Этот механизм может быть быстрее, чем вызов метода findViewById() для каждого представления в макете.
Идентификаторы не так необходимы, как без привязки данных, но все же есть некоторые случаи, когда доступ к представлениям необходим из кода.
Переменные
Библиотека привязки данных генерирует методы доступа для каждой переменной, объявленной в макете. Например, следующий макет генерирует методы setter и getter в классе привязки для переменных user, image и note:
<data>
<import type="android.graphics.drawable.Drawable"/>
<variable name="user" type="com.example.User"/>
<variable name="image" type="Drawable"/>
<variable name="note" type="String"/>
</data>
ViewStubs
В отличие от обычных представлений, объекты ViewStub изначально невидимы. Когда они становятся видимыми или явно раздуваются, они заменяют себя в макете, раздувая другой макет.
Поскольку ViewStub исчезает из иерархии View, View в объекте привязки также должен исчезнуть, чтобы его можно было заявить для сборки мусора.
Поскольку представления являются окончательными, объект ViewStubProxy заменяет ViewStub в сгенерированном классе привязки, предоставляя вам доступ к ViewStub, когда он существует, и доступ к развернутой иерархии представлений, когда ViewStub развернут.
При раздувании другого макета необходимо установить привязку для нового макета.
Поэтому ViewStubProxy должен прослушивать ViewStub
OnInflateListener и устанавливать привязку, когда это необходимо. Поскольку одновременно может существовать только один прослушиватель, ViewStubProxy позволяет задать OnInflateListener, который вызывается после установления привязки.
Немедленное связывание
Когда переменная или наблюдаемый объект меняется, привязка должна измениться до следующего кадра. Однако иногда привязку необходимо выполнить немедленно. Чтобы принудительно выполнить его, используйте метод executePendingBindings().
Динамические переменные
В некоторых случаях конкретный класс привязки неизвестен. Например, RecyclerView.Adapter, работающий с произвольными макетами, не знает конкретный класс привязки. Оно должно присваивать значение привязки во время вызова метода onBindViewHolder().
В примере ниже все макеты, с которыми связывается RecyclerView, имеют переменную item. У объекта BindingHolder есть метод getBinding(), который возвращает базовый класс ViewDataBinding.
Kotlin
override fun onBindViewHolder(holder: BindingHolder, position: Int) { item: T = items.get(position) holder.binding.setVariable(BR.item, item); holder.binding.executePendingBindings(); }
Java
public void onBindViewHolder(BindingHolder holder, int position) { final T item = items.get(position); holder.getBinding().setVariable(BR.item, item); holder.getBinding().executePendingBindings(); }
Фоновый поток
Вы можете изменить модель данных в фоновом потоке, если это не коллекция. Привязка данных локализует каждую переменную или поле во время оценки, чтобы избежать проблем с параллелизмом.
Названия классов для пользовательских привязок
По умолчанию класс привязки генерируется на основе имени файла макета, начиная с заглавной буквы, удаляя символы подчеркивания ( _ ), заглавными буквами следующую букву и добавляя суффикс слова Binding. Например, файл макета contact_item.xml генерирует класс ContactItemBinding. Класс помещается в пакет databinding в пакете модуля. Например, если пакет модуля – com.example.my.app, то класс привязки размещается в пакете com.example.my.app.databinding.
Классы привязки можно переименовать или поместить в другие пакеты, изменив атрибут class элемента data. Например, следующий макет генерирует класс привязки ContactItem в пакете databinding в текущем модуле:
<data class="ContactItem">
...
</data>
Вы можете сгенерировать класс привязки в другом пакете, добавив перед именем класса точку. В следующем примере класс привязки создается в пакете модуля:
<data class=".ContactItem">
...
</data>
Вы также можете использовать полное название пакета, в котором хотите создать класс привязки. В следующем примере создается класс привязки ContactItem в пакете com.example:
<data class="com.example.ContactItem">
...
</data>
Дополнительные ресурсы
Дополнительную информацию о привязке данных можно найти в следующих ресурсах.
- Примеры использования библиотеки привязки данных Android
- Как привязывать данные в Android
- Привязка данных: выводы
Рекомендуем
- Примечание. Текст ссылки показывается, когда JavaScript отключен.
- Макеты и выражения привязки
- Библиотека привязки данных
- Посмотреть привязку