View binding не работает

ViewBinding не работает для макета, включенного в элемент RecyclerView

Это мой макет элемента RecyclerView

Вот как я получаю доступ к представлениям внутри включенного макета

У меня нет ошибки времени компиляции, но возникает это исключение при запуске приложения

Включение макета в Activity или Fragment работает для меня, но не работает при использовании в Recycler View.

Я пробовал несколько решений, представленных на этом форуме для аналогичных исключений, но ни одно из них не работало для представления ресайклера и не отвечало на вопрос об использовании 0

1 ответ

RecyclerView работает путем создания и повторного использования связки ViewHolder , которые содержат макет представления для отображения деталей элемента. Вы устанавливаете их в методе onCreateViewHolder , где вы:

  • надуть макет для элемента
  • передать это расширенное представление конструктору ViewHolder

На самом деле вы не раздуваете макет, вы делаете

Функция bind в компоненте Binding берет уже завышенную иерархию представлений и пытается найти все компоненты с известными ей идентификаторами. Так, например, он пытается найти layoutSectionHeader , чтобы назначить binding.layoutSectionHeader этому представлению.

Проблема в том, что этого нет в макете parent , который вы передаете, потому что это просто макет RecyclerView , он не содержит материала из макета ViewHolder . Итак, bind не работает — представления не могут быть привязаны к ним. Вместо этого вам нужно позвонить inflate

Источник

viewBinding не работает в студии Android. в чем проблема?

Когда я использую привязку представления и вызываю с ним представление И я обрабатываю событие и запускаю программу, когда я нажимаю на представление, чтобы проверить его, ничего не происходит

Это мой build.gradle

3 ответа

Ваша настройка привязки просмотра в методе onCreate вызывает проблему см. — https: / /developer.android.com/topic/libraries/view-binding#activities для справки. Лучше всего объявить вашу переменную привязки выше onCreate как latinit, например: private lateinit var binding: ActivityMainBinding Затем вы должны установить переменную привязки внутри onCreate на завышаемый класс привязки — binding = ActivityMainBinding.inflate(layoutInflater) После этого получите корневое представление — val view = binding.root — и используйте это вместо того, чтобы установить представление содержания setContentView(view) В целом ваш код должен выглядеть так

class MainActivity: AppCompatActivity () <

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

Когда вы используете привязку

Тогда вы должны использовать его корень в качестве представления содержимого, поэтому

Включить функцию привязки данных, как показано ниже

Источник

Долгожданный 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 требовалась дополнительная настройка.

В целом, 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 :

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

Источник

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

kotlinx.android.synthetic is no longer a recommended practice. Removing in favour of explicit findViewById

Кратко о Kotlin Android Extensions

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

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

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

Проблемы Kotlin Android Extensions

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

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:

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

Будет сгенерирован класс ResultProfileBinding, содержащий 2 поля: TextView name и Button button.

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

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

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

Использовать viewBinding можно так:

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

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

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

Источник

Читайте также:  Iphone 7 не работает наушники зарядка работают
Оцените статью