Русский
Русский
English
Статистика
Реклама

Viewbinding

Kotlin Android Extensions deprecated. Что делать? Инструкция по миграции

03.11.2020 00:14:12 | Автор: admin
Возможно, вы уже слышали, что Kotlin Android Extensions плагин для Kotlin теперь deprecated.
kotlinx.android.synthetic is no longer a recommended practice. Removing in favour of explicit findViewById

Безусловно, это было очень удобно, особенно если у вас проект полностью на Kotlin. Однако, мир меняется и теперь нужно искать альтернативы. В этой статье мы кратко рассмотрим, что такое плагин Kotlin Android Extension, какие были проблемы с ним и что теперь нам, Android-разработчикам делать. Частично, использовался материал этой статьи. Итак, поехали.

Кратко о Kotlin Android Extensions


Kotlin Android Extensions это плагин для Kotlin, позволяющий восстанавливать view из Activities, Fragments, и Views без написания стандартного бойлерплэйт-кода типа findViewById.
Плагин генерирует дополнительный код, который позволяет получить доступ к view в виде XML, так же, как если бы вы имели дело с properties с именем id, который вы использовали при определении структуры.

Также он создаёт локальный кэш view. При первом использовании свойства, плагин выполнит стандартный findViewById. В последующем, view будет восстановлен из кэша, поэтому доступ к нему будет быстрее.

Если это всё так удобно, то зачем его сделали deprecated?

Проблемы Kotlin Android Extensions


  • Используется глобальный нэйминг идентификаторов. Могут возникнуть ситуации, когда один и тот же идентификатор имеется у разных view в разных лэйаутах соответственно только на этапе работы приложения вы узнаете о том, что использовали не тот id.
  • Возможно использовать только в проектах на Kotlin (кэп)
  • Отсутствует Null Safety. В случае, когда view представлена в одной конфигурации и отсутствует в другой может возникнуть краш, т.к отсутствует обработка таких ситуаций
  • Невозможно использовать в многомодульных проектах. Очень распространённый сценарий: у вас есть модуль UI Kit, хранящий общие UI-компоненты, которые вы хотите переиспользовать в других модулях. До сих пор висит issues которое вряд ли поправят. В таком сценарии обычно используют старый добрый findViewById :(
  • Резюмируя приведённые недостатки, нетрудно понять, что этот подход не идеален хотя, безусловно, очень удобен на небольших проектах. На больших проектах с многомодульной архитектурой и сотнями экранов использование Kotlin Android Extensions уже не кажется идеальным решением.

Альтернативные способы


  • Использование KotterKnife (кек, даже не думайте).
  • Старый добрый FindViewById() уже получше, но так себе.
  • Использование AndroidAnnotations (привет из 2015)
  • View Binding от Google бинго!


View Binding от Google


Итак, победителем в этом списке выглядит ViewBinding от Google (не путайте с DataBinding). Давайте кратко рассмотрим, что это такое.

View Binding это инструмент, который позволяет проще писать код для взаимодействия с view. При включении View Binding в определенном модуле он генерирует binding классы для каждого файла разметки (layout) в модуле. Объект сгенерированного binding класса содержит ссылки на все view из файла разметки, для которых указан android:id

Главные преимущества View Binding это Null safety и Type safety.

Начало работы с View Binding


Начать работать с ViewBinding достаточно просто. Нужно добавить опцию в build.gradle:

android {    ...    buildFeatures {        viewBinding true    }}


После этого можно уже использовать. Каждый сгенерированный binding класс содержит ссылку на корневой view разметки (root) и ссылки на все view, которые имеют id. Имя генерируемого класса формируется как название файла разметки, переведенное в camel case + Binding. Например, для файла разметки 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, содержащий 2 поля: TextView name и Button button.

Использование в Activity


Например у вас вот такой layout:

<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://personeltest.ru/away/schemas.android.com/apk/res/android"    xmlns:app="http://personeltest.ru/away/schemas.android.com/apk/res-auto"    xmlns:tools="http://personeltest.ru/away/schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".MainActivity">    <TextView        android:id="@+id/textView"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="Hello World!"        app:layout_constraintBottom_toBottomOf="parent"        app:layout_constraintLeft_toLeftOf="parent"        app:layout_constraintRight_toRightOf="parent"        app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>


Результат работы ViewBinding:

public final class ActivityMainBinding implements ViewBinding {  @NonNull  private final ConstraintLayout rootView;  @NonNull  public final TextView textView;


Использовать viewBinding можно так:
private lateinit var binding: ResultProfileBindingoverride fun onCreate(savedInstanceState: Bundle?) {    super.onCreate(savedInstanceState)    binding = ResultProfileBinding.inflate(layoutInflater)    val view = binding.root    setContentView(view)}


И теперь, после того, как получили ссылки на view:

binding.name.text = viewModel.namebinding.button.setOnClickListener { viewModel.userClicked() }


Если вы используете ViewBinding во фрагменте и держите ссылку на binding во фрагменте (а не только в методе onCreateView()) то не забывайте очищать ссылки в методе onDestroyView().

Пример:
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}


Это необходимо делать из-за жизненного цикла фрагмента и view:
image

В целом, переключиться на ViewBinding достаточно не сложно, хотя и жаль, что Kotlin Android Extensions объявлен deprecated. Не забудьте присоединиться к нам в Telegram, а на платформе AndroidSchool.ru публикуются полезные материалы для Android-разработчика и современные туториалы.

Полезные ссылки:

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru