Просмотр привязки. Часть Android Jetpack .
Привязка представления — это функция, которая упрощает написание кода, взаимодействующего с представлениями. Как только привязка представления включена в модуле, он генерирует класс привязки для каждого файла макета XML, присутствующего в этом модуле. Экземпляр класса привязки содержит прямые ссылки на все представления, имеющие идентификатор в соответствующем макете.
В большинстве случаев привязка представления заменяет findViewById
.
Настраивать
Привязка представления включается для каждого модуля отдельно. Чтобы включить привязку представления в модуле, установите для параметра сборки viewBinding
значение true
в файле build.gradle
уровня модуля, как показано в следующем примере:
классный
android { ... buildFeatures { viewBinding true } }
Котлин
android { ... buildFeatures { viewBinding = true } }
Если вы хотите, чтобы файл макета игнорировался при создании классов привязки, добавьте tools:viewBindingIgnore="true"
в корневое представление этого файла макета:
<LinearLayout
...
tools:viewBindingIgnore="true" >
...
</LinearLayout>
Использование
Если привязка представления включена для модуля, класс привязки создается для каждого файла макета XML, содержащегося в модуле. Каждый класс привязки содержит ссылки на корневое представление и все представления, имеющие идентификатор. Имя класса привязки генерируется путем преобразования имени XML-файла в регистр Паскаля и добавления в конец слова «Привязка».
Например, рассмотрим файл макета с именем result_profile.xml
, который содержит следующее:
<LinearLayout ... >
<TextView android:id="@+id/name" />
<ImageView android:cropToPadding="true" />
<Button android:id="@+id/button"
android:background="@drawable/rounded_button" />
</LinearLayout>
Созданный класс привязки называется ResultProfileBinding
. Этот класс имеет два поля: TextView
с именем name
и Button
с именем button
. ImageView
в макете не имеет идентификатора, поэтому в классе привязки на него нет ссылки.
Каждый класс привязки также включает метод getRoot()
, предоставляющий прямую ссылку на корневое представление соответствующего файла макета. В этом примере метод getRoot()
в классе ResultProfileBinding
возвращает корневое представление LinearLayout
.
В следующих разделах показано использование созданных классов привязки в действиях и фрагментах.
Используйте привязку представления в действиях
Чтобы настроить экземпляр класса привязки для использования с действием, выполните следующие шаги в методе onCreate()
действия:
- Вызовите статический метод
inflate()
включенный в сгенерированный класс привязки. При этом создается экземпляр класса привязки, который будет использоваться действием. - Получите ссылку на корневое представление, вызвав метод
getRoot()
или используя синтаксис свойств Kotlin . - Передайте корневое представление в
setContentView()
чтобы сделать его активным представлением на экране.
Эти шаги показаны в следующем примере:
Котлин
private lateinit var binding: ResultProfileBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ResultProfileBinding.inflate(layoutInflater) val view = binding.root setContentView(view) }
Ява
private ResultProfileBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ResultProfileBinding.inflate(getLayoutInflater()); View view = binding.getRoot(); setContentView(view); }
Теперь вы можете использовать экземпляр класса привязки для ссылки на любое представление:
Котлин
binding.name.text = viewModel.name binding.button.setOnClickListener { viewModel.userClicked() }
Ява
binding.name.setText(viewModel.getName()); binding.button.setOnClickListener(new View.OnClickListener() { viewModel.userClicked() });
Использовать привязку представления во фрагментах
Чтобы настроить экземпляр класса привязки для использования с фрагментом, выполните следующие шаги в методе onCreateView()
фрагмента:
- Вызовите статический метод
inflate()
включенный в сгенерированный класс привязки. При этом создается экземпляр класса привязки для использования фрагментом. - Получите ссылку на корневое представление, вызвав метод
getRoot()
или используя синтаксис свойств Kotlin . - Верните корневое представление из метода
onCreateView()
, чтобы сделать его активным представлением на экране.
Котлин
private var _binding: ResultProfileBinding? = null // This property is only valid between onCreateView and // onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { _binding = ResultProfileBinding.inflate(inflater, container, false) val view = binding.root return view } override fun onDestroyView() { super.onDestroyView() _binding = null }
Ява
private ResultProfileBinding binding; @Override public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { binding = ResultProfileBinding.inflate(inflater, container, false); View view = binding.getRoot(); return view; } @Override public void onDestroyView() { super.onDestroyView(); binding = null; }
Теперь вы можете использовать экземпляр класса привязки для ссылки на любое представление:
Котлин
binding.name.text = viewModel.name binding.button.setOnClickListener { viewModel.userClicked() }
Ява
binding.name.setText(viewModel.getName()); binding.button.setOnClickListener(new View.OnClickListener() { viewModel.userClicked() });
Предоставление подсказок для различных конфигураций
Когда вы объявляете представления в нескольких конфигурациях, иногда имеет смысл использовать другой тип представления в зависимости от конкретного макета. Следующий фрагмент кода показывает пример этого:
# in res/layout/example.xml
<TextView android:id="@+id/user_bio" />
# in res/layout-land/example.xml
<EditText android:id="@+id/user_bio" />
В этом случае вы можете ожидать, что сгенерированный класс предоставит поле userBio
типа TextView
, поскольку TextView
является общим базовым классом. Из-за технических ограничений генератор кода привязки представления не может это определить и вместо этого генерирует поле View
. Для этого потребуется позднее привести поле с binding.userBio as TextView
.
Чтобы обойти это ограничение, привязка представления поддерживает атрибут tools:viewBindingType
, позволяющий указать компилятору, какой тип использовать в сгенерированном коде. В предыдущем примере вы можете использовать этот атрибут, чтобы компилятор сгенерировал поле как TextView
:
# in res/layout/example.xml (unchanged)
<TextView android:id="@+id/user_bio" />
# in res/layout-land/example.xml
<EditText android:id="@+id/user_bio" tools:viewBindingType="TextView" />
В другом примере предположим, что у вас есть два макета: один содержит BottomNavigationView
, а другой — NavigationRailView
. Оба класса расширяют NavigationBarView
, который содержит большую часть деталей реализации. Если вашему коду не нужно точно знать, какой подкласс присутствует в текущем макете, вы можете использовать tools:viewBindingType
чтобы установить сгенерированный тип NavigationBarView
в обоих макетах:
# in res/layout/navigation_example.xml
<BottomNavigationView android:id="@+id/navigation" tools:viewBindingType="NavigationBarView" />
# in res/layout-w720/navigation_example.xml
<NavigationRailView android:id="@+id/navigation" tools:viewBindingType="NavigationBarView" />
Привязка представления не может проверить значение этого атрибута при создании кода. Чтобы избежать ошибок времени компиляции и выполнения, значение должно соответствовать следующим условиям:
- Значение должно быть классом, наследуемым от
android.view.View
. Значение должно быть суперклассом тега, в котором оно размещено. Например, следующие значения не работают:
<TextView tools:viewBindingType="ImageView" /> <!-- ImageView is not related to TextView. --> <TextView tools:viewBindingType="Button" /> <!-- Button is not a superclass of TextView. -->
Последний тип должен разрешаться последовательно во всех конфигурациях.
Отличия от findViewById
Привязка представления имеет важные преимущества перед использованием findViewById
:
- Нулевая безопасность: поскольку привязка представления создает прямые ссылки на представления, риск возникновения исключения нулевого указателя из-за недопустимого идентификатора представления отсутствует. Кроме того, если представление присутствует только в некоторых конфигурациях макета, поле, содержащее его ссылку в классе привязки, помечается
@Nullable
. - Безопасность типов: поля в каждом классе привязки имеют типы, соответствующие представлениям, на которые они ссылаются в XML-файле. Это означает, что нет риска исключения приведения класса.
Эти различия означают, что несовместимость между вашим макетом и вашим кодом приводит к сбою сборки во время компиляции, а не во время выполнения.
Сравнение с привязкой данных
Привязка представления и привязка данных создают классы привязки, которые можно использовать для прямой ссылки на представления. Однако привязка представления предназначена для обработки более простых случаев использования и предоставляет следующие преимущества по сравнению с привязкой данных:
- Ускоренная компиляция: привязка представления не требует обработки аннотаций, поэтому время компиляции сокращается.
- Простота использования: привязка представления не требует наличия XML-файлов макета со специальными тегами, поэтому его можно быстрее внедрить в свои приложения. Как только вы включаете привязку представления в модуле, она автоматически применяется ко всем макетам этого модуля.
С другой стороны, привязка представления имеет следующие ограничения по сравнению с привязкой данных:
- Привязка представления не поддерживает переменные макета или выражения макета , поэтому ее нельзя использовать для объявления динамического содержимого пользовательского интерфейса прямо из файлов макета XML.
- Привязка представления не поддерживает двустороннюю привязку данных .
По этим соображениям в некоторых случаях лучше всего использовать в проекте как привязку представления, так и привязку данных. Вы можете использовать привязку данных в макетах, требующих расширенных функций, и использовать привязку представления в макетах, которые этого не требуют.
Дополнительные ресурсы
Дополнительные сведения о привязке представления см. в следующих дополнительных ресурсах:
Образцы
Блоги
Видео
{% дословно %}Рекомендуется для вас
- Примечание: текст ссылки отображается, когда JavaScript отключен.
- Миграция с синтетики Kotlin на привязку представления Jetpack
- Макеты и выражения привязки
- Архитектура приложения: уровень пользовательского интерфейса — Начало работы — Разработчики Android