Просмотр привязки. Часть 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() действия:

  1. Вызовите статический метод inflate() включенный в сгенерированный класс привязки. При этом создается экземпляр класса привязки, который будет использоваться действием.
  2. Получите ссылку на корневое представление, вызвав метод getRoot() или используя синтаксис свойств Kotlin .
  3. Передайте корневое представление в 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() фрагмента:

  1. Вызовите статический метод inflate() включенный в сгенерированный класс привязки. При этом создается экземпляр класса привязки для использования фрагментом.
  2. Получите ссылку на корневое представление, вызвав метод getRoot() или используя синтаксис свойств Kotlin .
  3. Верните корневое представление из метода 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-файлов макета со специальными тегами, поэтому его можно быстрее внедрить в свои приложения. Как только вы включаете привязку представления в модуле, она автоматически применяется ко всем макетам этого модуля.

С другой стороны, привязка представления имеет следующие ограничения по сравнению с привязкой данных:

По этим соображениям в некоторых случаях лучше всего использовать в проекте как привязку представления, так и привязку данных. Вы можете использовать привязку данных в макетах, требующих расширенных функций, и использовать привязку представления в макетах, которые этого не требуют.

Дополнительные ресурсы

Дополнительные сведения о привязке представления см. в следующих дополнительных ресурсах:

Образцы

Блоги

Видео

{% дословно %} {% дословно %} {% дословно %} {% дословно %}