- ViewBinding не работает для макета, включенного в элемент RecyclerView
- 1 ответ
- viewBinding не работает в студии Android. в чем проблема?
- 3 ответа
- Долгожданный View Binding в Android
- Как включить
- Как использовать
- Отличия от других подходов
- Использование в RecyclerView.ViewHolder
- Делаем Android View Binding удобным c Kotlin
- Стандартный способ работы с View Binding
- Kotlin Delegated Property в бой
- Момент, когда что-то пошло не так.
- Kotlin Android Extensions deprecated. Что делать? Инструкция по миграции
- Кратко о Kotlin Android Extensions
- Проблемы Kotlin Android Extensions
- Альтернативные способы
- View Binding от Google
- Начало работы с View Binding
- Использование в Activity
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:
Источник