View binding android custom view

Долгожданный View Binding в Android

Пару дней назад Google выпустил Android Studio 3.6 Canary 11, главным нововведением в которой стал View Binding, о котором было рассказано еще в мае на Google I/O 2019.

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

Как включить

Чтобы включить View Binding в модуле надо добавить элемент в файл build.gradle :

Также можно указать, что для определенного файла разметки генерировать binding класс не надо. Для этого надо указать аттрибут tools:viewBindingIgnore=»true» в корневой view в нужном файле разметки.

Как использовать

Каждый сгенерированный binding класс содержит ссылку на корневой view разметки ( root ) и ссылки на все view, которые имеют id. Имя генерируемого класса формируется как «название файла разметки», переведенное в camel case + «Binding».

Например, для файла разметки result_profile.xml :

Будет сгенерирован класс ResultProfileBinding , содержащий 2 поля: TextView name и Button button . Для ImageView ничего сгенерировано не будет, как как оно не имеет id . Также в классе ResultProfileBinding будет метод getRoot() , возвращающий корневой LinearLayout .

Чтобы создать объект класса ResultProfileBinding , надо вызвать статический метод inflate() . После этого можно использовать корневой view как content view в Activity :

Позже binding можно использовать для получения view:

Отличия от других подходов

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

При этом, если какая-то view имеется в одной конфигурации разметки, но отсутствует в другой ( layout-land , например), то для нее в binding классе будет сгенерировано @Nullable поле.

Также, если в разных конфигурациях разметки имеются view с одинаковыми id, но разными типами, то для них будет сгенерировано поле с типом android.view.View .
(По крайней мере, в версии 3.6 Canary 11)

А вообще, было бы удобно, если бы сгенерированное поле имело наиболее возможный специфичный тип. Например, чтобы для Button в одной конфигурации и TextView в другой генерировалось поле с типом TextView ( public class Button extends TextView ).

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

Использование в RecyclerView.ViewHolder

Ничего не мешает использовать View Binding при создании view для RecyclerView.ViewHolder :

Однако, для создания такого ViewHolder придется написать немного бойлерплейта:

Было бы удобнее, если при работе с RecyclerView.ViewHolder метод inflate(. ) не будет иметь параметр layoutInflater , а будет сам получать его из передаваемого parent .

Тут нужно ещё упомянуть, что при использовании View Binding поиск view через findViewById() производится только один раз при вызове метода inflate() . Это дает преимущество над kotlin-android-extensions , в котором кеширование view по умолчанию работало только в Activity и Fragment , а для RecyclerView.ViewHolder требовалась дополнительная настройка.

Читайте также:  Шнур hdmi для андроид

В целом, View Binding это очень удобная вещь, которую легко начать использовать в существующих проектах. Создатель Butter Knife уже рекомендует переключаться на View Binding.

Немного жаль, что такой инструмент не появился несколько лет назад.

Источник

Делаем Android View Binding удобным c Kotlin

Привет! Меня зовут Кирилл Розов. Я автор Telegram канала Android Broadcast. Очень люблю Kotlin и мне нравится с помощью его возможностей упрощать разработку. С такой задачей я недавно столкнулся, когда на новом Android проекте начали использовать View Binding.

Эта возможность появилась в Android Studio 3.6, но на самом деле она не совсем новая, а облегченный вариант Android Data Binding. Зачем столько усложнений? Проблема была в скорости — множество разработчиков использовали Android Data Binding только для генерации кода со ссылками на View и игнорировали другие возможности библиотеки. Чтобы ускорить генерацию кода, создали View Binding . Однако стандартный способ работы с ней — это дублирование кода от которого хочется избавиться.

Стандартный способ работы с View Binding

Разберем работу View Binding на примере Fragment. У нас есть layout ресурс с именем profile.xml (содержимое его неважно). Если мы хотим использовать ViewBinding, тогда в стандартном варианте это будет выглядеть так:

Проблема здесь несколько:

  • Много лишнего кода
  • Копи паста: каждый Fragment будет иметь аналогичный кусок кода
  • Property viewBinding получается nullable и модифицируемым.

Давайте пробовать избавляться от этого с помощью Cилы Kotlin

Kotlin Delegated Property в бой

С помощью делегирования работы с property в Kotlin можно круто повторно использовать код и упростить некоторые задачи. Например, я применил это в случае с ViewBinding . Для этого я сделал свой делегат, который оборачивает создание ViewBinding и очистку его в нужный момент жизненного цикла:

и конечно же функцию-фабрику, чтобы не видеть как делегат создается:

После небольшого рефакторинга с новыми возможностями я получил следующее:

Вроде задача, которая ставилась, была достигнута. Что же могло пойти не так?

Момент, когда что-то пошло не так.

В какой-то момент возникла необходимость чистить View следующим образом:

Но в итоге я получил состояние, что моя ссылка на ViewBinding внутри делегируемого property уже была почищена. Попытка перенести очистку кода до вызова super.onDestroyView() не принесла успеха и я начал копаться в причинах. Виновником стала реализация вызова методов жизненного цикла у Fragment.viewLifecycleOwner .

Событие ON_DESTROY в Fragment.viewLifecycleOwner происходит до вызова Fragment.onDestroyView() , поэтому FragmentViewBindingProperty очищался раньше, чем я того ожидал. Решением стало отложить вызов операции очистки. Все вызовы жизненного цикла вызываются последовательно и на главном потоке, поэтому весь фикс свелся к откладыванию очистки с помощью Handler :

Полный код можно найти здесь и использовать его на своих проектах.

Источник

View Binding in Android

We have learnt that every time we need to access a view from our XML layout into our Java or Kotlin code, we must use findViewById(). It was okay for small/personal projects where we use 5 to 6 views in a layout. But for larger projects we have comparatively more views in a layout, and accessing each view using the same findViewById() is not really comfortable.

What is View Binding?

View binding is a feature that allows you to more easily write code that interacts with views. Once view binding is enabled in a module, it generates a binding class for each XML layout file present in that module

Simply put, this allows us to access the views from the layout file in a very simple way by linking variables of our Kotlin or Java code with the XML views. When a layout is inflated, it creates a Binding object, which contains all the XML views that are casted to the correct type. This makes it really easier for us since we can retrieve all views in one line of code.

Читайте также:  Космические рейнджеры андроид корабли

Getting started with View Binding

  1. Let’s start by enabling view binding in our project:

In build.gradle(:app) add the code in -> android

2. Before the onCreate() method, we create our binding object

3. Perform the following steps in onCreate() method:

  • Call the inflate() method to create an instance of the binding class for the activity to use.
  • Get reference to the root view
  • Pass the root view to setContentView() [setContentView(binding.root)] instead of layout [setContentView(R.id.activity_main)]

4. To get reference of any view, we can use the binding object:

Using View Binding in Fragments

We follow the same steps:

  1. Before the onCreateView() method, we create our binding object

2. Initialize our binding object in onCreateView()

3. To get reference of any view, we can use the binding object

Note: The name of the binding class is generated by converting the name of the XML file to camel case and adding the word “Binding” to the end. Similarly, the reference for each view is generated by removing underscores and converting the view name to camel case . For example, activity_main.xml becomes ActivityMainBinding, and you can access @id/text_view as binding.textView.

View binding has important advantages over using findViewById():

  • Null safety: Since view binding creates direct references to views, there’s no risk of a null pointer exception due to an invalid view ID.
  • Type safety: The fields in each binding class have types matching the views they reference in the XML file. This means that there’s no risk of a class cast exception.

Start using View Binding

If you’re intrigued by View Binding and want to learn more about it, here’s some resources for you to learn:

One-Liner ViewBinding Library

You would have noticed that to use View Binding, we need to call the static inflate() method included in the generated binding class ( which creates an instance of the binding class for the activity or fragment )

Yesterday I came across an awesome library that makes ViewBinding one-liner ( By removing the boilerplate code and easily set ViewBindings with a single line )

One-liner ViewBinding Library : [Click Here]

Источник

View Binding in Android Jetpack [Updated]

View binding is the current recommendation from the Google team for importing the views from XML to Activity , Fragment , or Adapter classes. View binding is a feature that allows us to more easily write code that interacts with views. In most cases, view binding replaces findViewById . It supports both Java and Kotlin.

To learn more about view binding check out the official documentation.

Table of Contents

Main advantages

The new ViewBinding feature has some advantages compared to the traditional approach and some of the libraries:

  • Null safety: view binding creates direct references to views, there’s no risk of a NullPointerException due to an invalid view ID. Also, when a view is only exists regarding some conditions, the field containing its reference in the binding class is marked with @Nullable .
  • Type safety: All the View binding fields are generated matching the same type as the ones referenced in XML, so there’s no need to typecast. This means that the risk of a class cast exception is much lower, since If for some reason your layout and code doesn’t match, the build will fail at compile time instead at runtime.
  • Speed: it doesn’t have any build time speed impact since it does not use annotation processors like ButterKnife or DataBinding.
Читайте также:  Пульт блютуз для андроид тв что это такое

Before getting started, check out another post on the jetpack,

View binding and Kotlin synthetics or ButterKnife

One of the most common questions asked about view binding is, “Should I use view binding instead of Kotlin synthetics or ButterKnife?” Both of these libraries are used successfully by many apps and solve the same problem.

For most apps we recommend trying out view binding instead of these libraries because view binding provides safer, more concise view lookup.

Setup View Binding

To enable view binding in a module, set the viewBinding build option to true in the module-level build.gradle file.

Usage

Once enabled for a project, view binding will generate a binding class for all of your layouts automatically. You don’t have to make changes to your XML — it’ll automatically work with your existing layouts.

You can use the binding class whenever you inflate layouts such as Fragment , Activity , or even a RecyclerView Adapter (or ViewHolder ).

For example, given a layout file called activity_main.xml:

The generated binding class is called ActivityMainBinding . This class has two fields: a TextView called textAppName and a Button called buttonGotoFragment .

Every binding class also includes a getRoot() method, providing a direct reference for the root view of the corresponding layout file. In this example, the getRoot() method in the ResultProfileBinding class returns the ConstraintLayout root view.

Use view binding in activities

To use View Binding in Activity, create an instance of the binding class, get the root view, and pass it to setContentView().

You can now use the instance of the binding class to reference any of the views:

Use view binding in fragments

In the onCreateView method, inflate your layout file and create the binding instance:

same like activity binding you can use the instance of the binding class to reference any of the views.

Disabling View Binding

If for any reason you want to disable View Binding on a specific layout, you can open it up and add the following statement.

Migrate from Kotlin synthetics to Jetpack view binding

Kotlin Android Extensions is deprecated, which means that using Kotlin synthetics for view binding is no longer supported. If your app uses Kotlin synthetics for view binding, use this guide to migrate to Jetpack view binding.

Update the Gradle file

Jetpack view binding is enabled on a module by module basis. For each module that uses view binding, set the viewBinding build option to true in the module-level build.gradle file:

Also,remove the line that enables Kotlin Android Extensions:

Now you can use the above mentioned options to work with activity and fragments.

Migrating From findViewById

2. add the binding class for your XML layout.

3. Now, replace setContentView() with the following:

Replace textView with binding.textView . Then add the binding. prefix to the rest of the views marked in red by the IDE.

Thanks for reading. You can download android view binding example in GITHUB.

If you have any questions, please feel free to leave a comment below.

Источник

Оцените статью