databinding android что это

Урок 18. Android Data Binding. Основы

В этом уроке знакомимся с Data Binding.

Полный список уроков курса:

В build.gradle файл модуля в секции android необходимо включить Data Binding:

Data Binding поможет организовать работу с View так, чтобы нам не пришлось писать кучу методов findViewById, setText, setOnClickListener и т.п. Давайте рассмотрим простой пример.

Есть класс Employee, который содержит в себе данные о работнике

поля: id, имя и адрес.

Мы хотим вывести имя и адрес работника на экран main_activity.xml:

Несложная задача. Для этого мы обычно пишем методы findViewById и setText. Тут все понятно.

Давайте рассмотрим, как это же можно сделать с помощью Data Binding.

Вносим изменения в main_activity.xml:

Обратите внимание, что мы не указываем id для View. В этом нет необходимости.

Как вы понимаете, нам остается лишь передать объект Employee в этот layout. И значения этого объекта будут подставлены в соответствующие TextView.

Это делается следующим образом.

Сначала создаем Employee объект.

Затем используем DataBindingUtil. Метод DataBindingUtil.setContentView внутри себя сделает привычный нам setContentView для Activity, а также настроит и вернет объект биндинга MainActivityBinding.

Метод setEmployee был сгенерирован в классе биндинга, т.к. мы описали переменную employee в layout файле. Этим методом мы передаем биндингу объект Employee. Биндинг возьмет значения employee.name и employee.address и поместит их (методом setText) в соответствующие TextView. Все, как мы и настраивали в layout.

Данные из Employee помещены в TextView.

Сразу хочу заметить, что если мы теперь в коде будем изменять объект Employee, то данные на экране меняться не будут. Они считались один раз и далее не отслеживаются (при такой реализации).

Чтобы экран получил новые данные, надо снова передать биндингу измененный объект Employee:

Или можно вызывать метод invalidateAll:

Биндинг считает новые данные с ранее полученного объекта Employee.

Поля в Employee в этом примере я сделал public. Но вы можете сделать их private и создать для них public get методы.

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

Эти возможности мы рассмотрим в следующих уроках.

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

28 марта 2016 г. DataBinding: ускоряем разработку приложений под Android

Каждый раз при виде километров строк с findViewById и «тернарок» с visibility у тебя дергается глаз? Знай — выход есть! Подробности — под катом.

1. Что за за зверь

Ни для кого не секрет, что самая скучная часть разработки приложений — это описывание поведения UI в зависимости от логики изменения данных. Сколько слез было пролито при написании (а в последствии и в поддержке) тривиального и почти бесполезного «треша», который занимал десятки, а то и сотни строк в классах практически каждой активности или фрагмента. О читабельности и вовсе не стоит говорить — разобраться, а тем более найти баг (который очень-то просто допустить) в джунглях однообразной логики — то еще приключение.

Вывод очевиден: нужно каким-то образом это автоматизировать. Как раз эту задачу и выполняет DataBinding — библиотека, с помощью которой максимально минимизируется связующий код между логикой приложения и ее представлением.

2. Интеграция

Чтобы продемонстрировать возможности сего чуда мы напишем небольшое приложение на примере профиля пользователя. Но прежде чем приступить давайте подключим наш волшебный инструмент к проекту.

Для интеграции биндинга нам необходимо использовать плагин Gradle версии не ниже, чем 1.5.0, поэтому обновим файл build.gradle проекта, добавив следующую строку:

Далее остается добавить элемент dataBinding в модульный build.gradle:

Синхронизируем Gradle и радуемся передовым технологиям в нашем проекте 🙂

3. Пробный заезд

Ну что ж, теперь можно создавать наш пример. Начнем с простого — создадим активность, в которой будут отображаться основные данные о пользователе, а именно: имя, фамилия, статус и индикатор «онлайн».

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

Следующим шагом создадим разметку. Ограничимся простыми TextView для отображения имени и статуса, и View — для индикатора:

Давайте вкратце пройдемся по всем странностям в разметке:

Теперь, по завершению всех необходимых шагов, давайте посмотрим, как будет выглядеть наш класс активности:

Здесь с помощью DataBindingUtil мы инициализируем лэйаут и в ответ получаем любезно сгенерированный для нас ActivityMainBinding (по умолчанию Binding-класс генерируется на основе имени файла макета переведенного в CamelCase с добавлением суффикса «Binding»), в котором и хранятся все ссылки на наши элементы интерфейса. Для того, чтобы заполнить их данными нужно просто задать объект пользователя с помощью метода setUser (название этого метода зависит от именования переменной в поле name блока variable).

Посмотрим на результат:

Да, этого кода достаточно для того, чтобы отобразить нужные нам данные 🙂 Но.

4. Это еще цветочки

У DataBinding есть собственный язык выражений для файлов разметки. Он в точности соответствует выражениям в Java и впечатляет своими возможностями. Ниже приведен перечень всех доступных операторов:

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

Нельзя не упомянуть и так называемый Null Coalescing Operator «??», который достаточно лаконично позволяет решить множество проверок на null. Вот как это выглядит:

Читайте также:  что такое гомогенный гель

Обе строки кода эквивалентны. Ну разве не находка? 🙂

Код, сгенерированный библиотекой DataBinding, также автоматически проверяет все объекты и предотвращает NullPointerException. Например, если в выражении @ поле status является null, то его значением будет являться значение по умолчанию — т.е. «null». Этот принцип работает и для примитивных типов данных.

Знакомый нам тег имеет еще одно свойство — с его помощью можно импортировать типы, необходимые нам для работы. К тому же, их можно сокращать для удобства и экономии места с помощью alias.

Работа с ресурсами здесь заслуживает отдельных похвал — практически все возможные ресурсы можно вызывать напрямую и комбинировать с логическими операторами. В примере с индикатором «онлайн» мы уже видели одну из реализаций — в атрибут android:background подставлялся нужный Drawable в зависимости от того, находится ли пользователь в сети. Так вот, представьте себе гибкость разметки, используя все допустимые ссылки:

Тип Нормальная ссылка Ссылка в выражении
String[] @array @stringArray
int[] @array @intArray
TypedArray @array @typedArray
Animator @animator @animator
StateListAnimator @animator @stateListAnimator
Color int @color @color
ColorStateList @color @colorStateList

Помимо всего перечисленного, не остается без внимания и @BindingAdapter. С его помощью можно переопределять поведение существующих атрибутов и создавать свои, не думая о attrs.xml.

Для этого нужно создать публичный статический метод, на вход которому будет приходить View нужного нам типа и значение, которое мы указываем в разметке. Сам метод нужно пометить аннотацией @BindingAdapter и в ее теле указать строку с именем атрибута.

К примеру, такой адаптер позволяет «повесить» на view любой метод без параметров в качестве OnClickListener:

Адаптеры также можно создавать для нескольких параметров одновременно. Например, так можно задать url на изображение и ресурс на случай ошибки при загрузке:

Но бывают случаи, когда необходимо преобразовать типы автоматически (например boolean в int (Visibility)). Тогда на смену адаптеру приходит @BindingConversion:

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

5. Пишем себе в удовольствие

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

Итак, первым делом добавим фотографию пользователя и возможность добавить его в друзья. Допишем необходимые поля в модель User:

Затем разместим в разметке ImageView для аватара профиля:

Для загрузки изображения сработает написанный нами ранее адаптер loadImage. Теперь добавим кнопки добавления и удаления из френдлиста:

Вы, наверное, заметили, что объект user был переименован на viewModel, хотя на самом деле это совсем другой объект. ViewModel — это связующее звено между View и моделью данных, в которой описывается вся логика поведения. О модели MVVM (Model-View-ViewModel) мы поговорим в следующий статье и подробно разберем как правильно ее реализовать, а пока просто запомним, что логика поведения должна размещаться в отдельном объекте. Вот наша VM для профиля:

Как видно, VM наследуется от BaseObservable. Это дает нам возможность оповещать биндинг о изменениях внутри с помощью notifyPropertyChanged, куда передается BR.variable. Название переменной генерируется так же, как id в стандартном R-классе, а помечаются они аннотацией @Bindable (в нашем случае — в геттерах).

Поле isLoaded будет служить флагом для индикатора загрузки, который будет переключаться на 1 секунду каждый раз, при вызове changeFriendshipStatus. Осталось только немного модифицировать лэйаут с кнопками и добавить ProgressBar:

Теперь каждый раз, когда мы будем нажимать на кнопку удаления или добавления в друзья — RelativeLayout будет заменяться ProgressBar’ом на секунду и возвращаться обратно. Самое время запустить и посмотреть на результат.

6. Дальше — интересней

ObservableField представляют собой автономные наблюдаемые объекты, которые имеют одно поле. К нему можно обращаться с помощью методов get() и set(), которые автоматически оповещают View об изменениях. Чтобы использовать его, нужно просто создать public final поле в классе VM. Для этого обновим нашу ProfileViewModel:

Нетрудно заметить, насколько меньше стало кода, хоть он и выполняет все те же функции, что и раньше. Стоит заметить, что почти для каждого примитивного типа есть его Observable-аналог. В свою очередь мы использовали ObservableBoolean.

В библиотеке, к сожалению, еще не реализован двусторонний биндинг, но не стоит расстраиваться — у нас есть все, что бы справиться с этой задачей самостоятельно! Двусторонний биндинг — это когда не только данные влияют на то, что отображается во View, но и наоборот — когда введенные пользователем данные изменяют модель. Давайте попробуем сделать это на примере EditText.

Первым делом обратим внимание на то, что по каким-то причинам отсутствует ObservableString, а потому создадим свой:

Логика простая и в пояснениях, не нуждается, поэтому перейдем к реализации адаптера. Основной трюк в том, чтобы добавить TextWatcher к EditText и в колбэке обновлять наш ObservableString:

Теперь можно просто указать в XML наш ObservableString и дело в шляпе!

7. Сладости в придачу

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

RecyclerBindingAdapter — это универсальный адаптер для простых списков. Один и на весь проект. Больше не нужно создавать их каждый раз отдельно для каждого списка 🙂 Давайте взглянем, как это происходит:

А создать его можно всего в одну строку:

BR.data — это имя variable в xml-файле, а list — наша выборка. Задаем адаптер RecyclerView и забываем о головной боли раз и навсегда. Забегая наперед, задам вопрос: а как нам конфигурировать RecyclerView не обращаясь к биндингу напрямую? Здесь-то и напрашивается следующая фича — RecyclerConfiguration:

Эта простая обертка не засоряет код ObservableFileds позволяет указывать конфигурацию прямо в XML, предварительно заполнив ее из кода.

Читайте также:  какой орех нельзя белкам

Немного дописав ViewModel, мы получим вот такую имитацию realtime-событий:

8. Ложка дегтя

На сегодняшний день DataBinding находится на стадии разработки, а потому при использовании проявляется целый ряд неприятностей. К ним можно отнести отсутствие двустороннего биндинга и некоторых полей «из коробки». Помимо этого есть и проблемы с поддержкой в Android Studio: часто выражения в разметке распознаются как ошибки, пропадает класс BR или весь пакет binding целиком (решается с помощью Build → Clean Project). В разметке есть проблемы с кодированием (к примеру, вместо оператора «&&» приходится писать «&&») и прочие. Но стоит рассматривать эти проблемы как временные неудобства, ведь разработка ведется активно, а технология стоит того, чтобы немножко потерпеть 🙂

9. Заключение

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

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

Спасибо за внимание!

Исходный код приложения на GitHub.

Нужен MVP, разработка под iOS, Android или прототип приложения? Ознакомьтесь с нашим портфолио и сделайте заказ уже сегодня!

Источник

Легкий DataBinding для Android

Здравствуйте уважаемые читатели. Все мы любим и используем DataBinding, который представила компания Google несколько лет назад, для связи модели данных с вьюшками через ViewModel. В этой статье, хочу поделиться с вами, как можно унифицировать этот процесс с помощью языка Kotlin, и уместить создание адаптеров для RecyclerView (далее RV), ViewPager и ViewPager2 в несколько строчек кода.

Начну с того, что раньше разрабатывали кастомные адаптеры, которые под капотом создавали ViewHolder’ы, и их написание, а тем более поддержка, занимала достаточно большое количество времени. Ниже приведу пример типичного адаптера для RV:

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

ViewModel, соответственно, содержит список моделей данных для адаптера, которые должны отображаться в RV, а фрагмент конфигурацию DataBindingRecyclerViewConfig.

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

Это все, что нужно сделать, чтобы связать данные из ViewModel с отображением списка в RV. Так же при создании адаптера можно назначить слушатели событий для байдинга вьюхолдера, такие как onItemClick, onItemCreate, onItemBind и другие.

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

Таким образом, создание адаптеров для отображения данных в RV, превратилось в простую задачу состоящую из пары строчек кода, где разработчику уже не надо думать о том, как поддерживать, фактически, не нужную часть presentation слоя. И даже, если модель данных изменится, достаточно будет поменять только её отображение, и связать его с новыми данными, не заботясь о поддержке адаптеров.

Аналогичный процесс создания адаптеров для ViewPager и ViewPager2, представлен в примере на github вместе с открытым кодом, ссылку на который, я разместил в конце статьи. В настоящий момент библиотека еще дорабатывается, и хочется получить адекватный фидбек, и пожелания по дальнейшему ее развитию. Так же в неё вошли вспомогательные функции для удобного создания байдинга, в том числе в связке с ViewModel. (LayoutInflater.createBinding, Fragment.createBindingWithViewModel, etc)

Спасибо, что дочитали до конца. Приятного кодинга и хорошего настроения)

Источник

Урок 8. Android Data Binding – основы

Продолжаем курс по обучению основам разработки мобильных приложений в Android Studio на языке Kotlin. В этом уроке познакомимся с Android Data Binding.

Data Binding Library

Библиотека Data Binding Library, которая является частью Android Jetpack, позволяет привязывать компоненты пользовательского интерфейса в макетах к источникам данных в приложении, используя декларативный формат, а не программно. Другими словами, Data Binding поможет организовать работу с View так, чтобы нам не пришлось писать кучу методов findViewById, setText, setOnClickListener и т.п.

Чтобы более тесно на практике познакомиться с чистой архитектурой и архитектурными компонентами, записывайтесь на продвинутый курс по разработке приложения «Чат-мессенжер»

В этом цикле уроков вы узнаете, как настроить Data Binding в проекте, что такое layout expressions, как работать с observable objects и как создавать кастомные Binding Adapters чтобы свести избыточность (boilerplate) вашего кода к минимуму.

С чего начать

В этом уроке, мы возьмем уже существующий проект и конвертируем его в Data Binding:

Приложение имеет один экран, который показывает некоторые статические данные и некоторые наблюдаемые данные, что означает, что при изменении данных пользовательский интерфейс будет автоматически обновляться. Данные предоставлены ViewModel. Model-View-ViewModel — это шаблон уровня представления, который очень хорошо работает с Data Binding. Вот диаграмма паттерна MVVM:

Если вы еще не знакомы с классом ViewModel из библиотек компонентов архитектуры, вы можете посмотреть официальную документацию. Мы знакомились с этим классом на прошлом уроке, ссылку на который вы видите в правом верхнем углу этого видео. Это класс, который предоставляет состояние пользовательского интерфейса для представления (Activity, Fragment, т.п.). Он выдерживает изменения ориентации и действует как интерфейс для остальных слоев вашего приложения.

Что нам понадобится

На этом этапе мы загрузим и запустим простое приложение-пример. Выполните в консоли команду:

Вы также можете клонировать или скачать репозиторий в виде Zip-файла по ссылке на GitHub

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

Читайте также:  при какой температуре можно мыть собаку в ванне

Этот экран отображает несколько различных полей и кнопку, по нажатию которой можно увеличить счетчик, обновить индикатор выполнения и изображение. Логика действий, происходящих на экране, описана в классе SimpleViewModel. Откройте его и посмотрите.

Используйте Ctrl + N, чтобы быстро найти класс в Android Studio. Используйте Ctrl + Shift + N, чтобы найти файл по его имени.

На Mac найдите класс с помощью Command + O и файл с помощью Command + Shift + O.

В классе SimpleViewModel описаны такие поля:

Кроме того, он позволяет пользователю увеличивать количество лайков методом onLike().

Пока SimpleViewModel содержит не самый интересный функционал, но здесь все в порядке. С другой стороны, класс главного экрана MainActivity имеет ряд проблем:

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

Подключаем Data Binding в проект

Первым шагом является включение библиотеки Data Binding в модули, которые будут ее использовать. Добавьте такие строки в файл сборки модуля app:

Источник

Быстрый старт Data Binding в Android

Введение

Профессионально андроид-разработкой занимаюсь чуть больше года, до этого разрабатывал по Windows Phone и мне понравилась возможность связывать данные из вью модели с самим View при помощи механизма Bindings. А после изучения RX, многие задачи стали решаться более чисто, вью-модель полностью отделилась от View. Она стала оперировать только моделью, совсем не заботясь о том, как она будет отображаться.

В Android такой строгости я не заметил, Activity или Fragment как простейшие представители контроллера чаще всего имеют полный доступ как ко View, так и к модели, зачастуя решая, какой View будет видим, решая таким образом чисто вьюшные задачи. Поэтому я довольно радостно воспринял новость о появлении Data Binding в Android на прошедшем Google IO.

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

Начало

Я использую Android Studio 1.3. Data binding поддерживает Android 2.1 и выше (API level 7+).

Для сборки используется новый android плагин для Gradle (нужна версия 1.3.0-beta1 и старше). Так как связи отрабатываются во время компиляции, нам понадобиться ещё один плагин к Gradle ‘com.android.databinding:dataBinder:1.0-rc0’. В отличие от того же Windows Phone где механизм привязок реализован глубоко по средством DependencyProperty и в RealTime, в Android эта функция реализуется как бы поверх обычных свойств, во время компиляции и дополнительной кодогенерации, поэтому в случае ошибок будьте готовы разбирать ответ от компилятора.

Итак, заходим в файл build.gradle, который лежит в корневом каталоге проекта (в нём идут настройки Gradle для всего проекта). В блоке dependencies вставляем:

Теперь подключим плагин к конкретному модулю, откроем build.gradle файл, который лежит внутри модуля. По умолчанию app/build.gradle и добавим строчку:

Настройка Layout

Мы должны обернуть наш внешний View в тег
Уже сейчас можно начать его использовать класс Binding для доступа к элементам интерфейса, без использования findViewById. В MainActivity добавим поле и перепишем метод onCreate:

Название поля берётся из Id View, без Id в биндере поле не появиться, если изменить Id View, то поле в биндере сразу же переметнуться. Если с зажатым CTRL нажать на название поля View, то сразу перейдешь к нему в файле разметки. Как по мне так уже одного такого функционала достаточно для того чтобы начать использовать биндинги.

Привязка данных

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

Изменим Layout, заменим содержимое LinearLayout на:

И в onCreate заменим последнюю строку на:

Запускаем. Всё работает.
Наверное у всех проектах в активити или в фрагментах встречается такие строчки:

Тут то мы и начинаем использовать непосредственно привязки данных. Перепишем модель:

И добавим в Layout:

На красные выделения студии игнорируем.
Так как мы используем класс View, то его нужно импортировать, добавим в ноду
Или используем его вместе с названием пакета:

Так же возможно в ноде

Конвертеры

Импорт в свою очередь даёт возможность писать конвертеры. Добавим в модель поле с датой рождения и удалим возраст:

Импортируем его в разметку:

Обратная связь и Binding

Попробуем сменить имя пользователя.
Добавим в Layout:

Запускаем и кликаем, тост всплыл, но имя не изменилось. Это случилось из-за того, что модель ни как не известила binder о своём изменении.

Можно создать новую модель и вставить её, но с точки зрения памяти это расточительно:

Или вытащить старую, заменить данные и вставить опять:

Но тогда обновятся все View, связанные с этой моделью. Лучшим вариантом будет связать модель с binder, чтобы она могла его оповестить о своём изменении. Для этого перепишем класс модели, добавив геттеры и сеттеры,

помечая геттеры атрибутом @Bindable, и добавив в сеттеры вызов notifyPropertyChanged(BR.lastName);

ObservableFields

По коллекциям аналогично, единственное приведу пример обращения ко ключу к Map:

Из View в Model

Теперь попробуем взять новое имя из UI, привязав EditText к некоторой модели. Так как внутри EditText крутится Editable, то и привязать будет к
Изменю MainActivity:

А в разметку добавлю:

Вот тут возникает проблема, если привязать ObservableField к EditText, то всё будет работать только в сторону View. Как я понял, проблема в том, что Editable, который лежит внутри ObservableField, отличается от того, который лежит внутри EditText.

Очень любопытно было увидеть библиотеку для поддержки Data Binding в Android от Google. В документации тоже нет информации про обратную связь данных, но я надеюсь на скорую её реализацию. После официального выхода стабильной версии можно будет посмотреть на интеграцию с JavaRX.

[ Оффициальная документация ]
[ Ссылка на мой простенький пример ]

Источник

Сказочный портал