- Урок 18. Android Data Binding. Основы
- Полный список
- Урок 21. Android Data Binding. Observable поля. Двусторонний биндинг.
- Observable поля
- BaseObservable
- Двусторонний биндинг
- Быстрый старт Data Binding в Android
- Введение
- Начало
- Настройка Layout
- Привязка данных
- Конвертеры
- Обратная связь и Binding
- ObservableFields
- Из View в Model
Урок 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:
Корневым элементом теперь является , а LinearLayout сместился внутрь него.
В секции data мы объявляем переменную с именем employee. Ее тип — ранее рассмотренный класс Employee. Теперь мы можем использовать эту переменную в атрибутах вьюшек этого layout. В первом TextView, в атрибуте text мы используем employee.name, а в втором TextView — employee.address.
Обратите внимание, что мы не указываем id для View. В этом нет необходимости.
Как вы понимаете, нам остается лишь передать объект Employee в этот layout. И значения этого объекта будут подставлены в соответствующие TextView.
Это делается следующим образом.
Сначала создаем Employee объект.
Затем используем DataBindingUtil. Метод DataBindingUtil.setContentView внутри себя сделает привычный нам setContentView для Activity, а также настроит и вернет объект биндинга MainActivityBinding.
MainActivityBinding — это сгенерированный класс. Имя этого класса берется из имени layout файла (т.е. main_activity), плюс слово Binding. MainActivityBinding все знает о нашем layout: какие View там есть, какие переменные (variable) мы там указывали, и как все это связать друг с другом, чтобы данные из переменных попадали в View.
Метод setEmployee был сгенерирован в классе биндинга, т.к. мы описали переменную employee в layout файле. Этим методом мы передаем биндингу объект Employee. Биндинг возьмет значения employee.name и employee.address и поместит их (методом setText) в соответствующие TextView. Все, как мы и настраивали в layout.
Данные из Employee помещены в TextView.
Сразу хочу заметить, что если мы теперь в коде будем изменять объект Employee, то данные на экране меняться не будут. Они считались один раз и далее не отслеживаются (при такой реализации).
Чтобы экран получил новые данные, надо снова передать биндингу измененный объект Employee:
Или можно вызывать метод invalidateAll:
Биндинг считает новые данные с ранее полученного объекта Employee.
Поля в Employee в этом примере я сделал public. Но вы можете сделать их private и создать для них public get методы.
Возможно, использование биндинга для пары TextView кажется бессмысленным. Но когда таких TextView десятки, то биндинг может избавить вас от написания кучи кода.
Кроме того, мы рассмотрели совсем простой случай использования биндинга. Но его возможности гораздо шире. Например, можно сделать так, чтобы при передаче в атрибут ImageView ссылки на картинку, биндинг запускал Picasso для загрузки этой картинки и помещал результат в ImageView. Или биндинг может сам отслеживать изменения в объекте с данными (в примере выше — это Employee ) и обновлять экран без каких-либо дополнительных методов.
Эти возможности мы рассмотрим в следующих уроках.
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник
Полный список
В этом уроке знакомимся с 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:
Корневым элементом теперь является , а LinearLayout сместился внутрь него.
В секции data мы объявляем переменную с именем employee. Ее тип — ранее рассмотренный класс Employee. Теперь мы можем использовать эту переменную в атрибутах вьюшек этого layout. В первом TextView, в атрибуте text мы используем employee.name, а в втором TextView — employee.address.
Обратите внимание, что мы не указываем id для View. В этом нет необходимости.
Как вы понимаете, нам остается лишь передать объект Employee в этот layout. И значения этого объекта будут подставлены в соответствующие TextView.
Это делается следующим образом.
Сначала создаем Employee объект.
Затем используем DataBindingUtil. Метод DataBindingUtil.setContentView внутри себя сделает привычный нам setContentView для Activity, а также настроит и вернет объект биндинга MainActivityBinding.
MainActivityBinding — это сгенерированный класс. Имя этого класса берется из имени layout файла (т.е. main_activity), плюс слово Binding. MainActivityBinding все знает о нашем layout: какие View там есть, какие переменные (variable) мы там указывали, и как все это связать друг с другом, чтобы данные из переменных попадали в View.
Метод setEmployee был сгенерирован в классе биндинга, т.к. мы описали переменную employee в layout файле. Этим методом мы передаем биндингу объект Employee. Биндинг возьмет значения employee.name и employee.address и поместит их (методом setText) в соответствующие TextView. Все, как мы и настраивали в layout.
Данные из Employee помещены в TextView.
Сразу хочу заметить, что если мы теперь в коде будем изменять объект Employee, то данные на экране меняться не будут. Они считались один раз и далее не отслеживаются (при такой реализации).
Чтобы экран получил новые данные, надо снова передать биндингу измененный объект Employee:
Или можно вызывать метод invalidateAll:
Биндинг считает новые данные с ранее полученного объекта Employee.
Поля в Employee в этом примере я сделал public. Но вы можете сделать их private и создать для них public get методы.
Возможно, использование биндинга для пары TextView кажется бессмысленным. Но когда таких TextView десятки, то биндинг может избавить вас от написания кучи кода.
Кроме того, мы рассмотрели совсем простой случай использования биндинга. Но его возможности гораздо шире. Например, можно сделать так, чтобы при передаче в атрибут ImageView ссылки на картинку, биндинг запускал Picasso для загрузки этой картинки и помещал результат в ImageView. Или биндинг может сам отслеживать изменения в объекте с данными (в примере выше — это Employee ) и обновлять экран без каких-либо дополнительных методов.
Эти возможности мы рассмотрим в следующих уроках.
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник
Урок 21. Android Data Binding. Observable поля. Двусторонний биндинг.
В этом уроке разберем, как настроить автоматическую передачу данных в View и обратно.
Полный список уроков курса:
Когда мы используем биндинг для обычного Java объекта, то экран не будет автоматически меняться при изменении значений в этом объекте.
Т.е. вы передаете объект Employee в биндинг, а затем можете сколько угодно менять в нем поля и ничего на экране меняться не будет. Вам надо будет снова руками передать измененный объект в биндинг или вызвать у биндинга метод invalidateAll, тогда экран отобразит актуальные данные.
В первом уроке по Data Binding я упоминал, что есть возможность сделать так, чтобы биндинг сам мониторил значения полей и обновлял экран, как только произошли какие-то изменения. Для этого надо использовать механизмы Observable.
Observable поля
Сделаем несколько Observable полей в классе Employee:
Для Java примитивов есть готовые Observable поля: ObservableInt, ObservableFloat и т.п. Для остальных используем ObservableField с указанием типа. Чтобы присвоить такому полю значение, используем метод set.
Поля name и salary делаем Observable. Их мы будем использовать в биндинге.
layout файл выглядит как обычно, в нем ничего менять не надо:
Теперь, передав в биндинг объект Employee, вы сможете менять значения его полей:
А биндинг сам отследит эти изменения и обновит экран.
Для коллекций есть классы ObservableArrayMap и ObservableArrayList.
Биндинг будет работать, даже если передавать значения в Observable поля не в UI потоке.
Рассмотрим еще один возможный сценарий использования ObservableField. Его можно использовать не только с отдельными полями объекта, но и с целым объектом.
Есть класс Employee:
Вполне может быть ситуация, когда нам в ViewModel (или в презентер) периодически «прилетает» из репозитория новый объект Employee и его надо отобразить в View.
В этом случае в ViewModel создаем поле ObservableField :
В это поле методом employee.set() репозиторий будет помещать новый Employee.
В layout в качестве переменной используем ViewModel.
Достаем из model объект employee и используем его поля в биндинге.
Теперь при обновлении значения в ObservableField будут изменены и поля в View без каких-либо дополнительных действий с нашей стороны.
BaseObservable
Есть еще один способ включить автобиндинг для Java объекта.
Делается это наследованием BaseObservable:
Поле id я оставил обычным. А поля name и salary будут отслеживаться биндингом. Для этого надо пометить get-методы аннотацией @Bindable, а в set-методах вызывать notifyPropertyChanged метод, который и будет уведомлять биндинг об изменениях значения поля.
В layout все будет как обычно.
Двусторонний биндинг
Биндинг может работать в обе стороны. Т.е. он будет не только передавать данные в View, но и получать их оттуда.
Рассмотрим на примере пары полей в Employee:
Поле name и статус enabled. Настроим биндинг этих полей в EditText и CheckBox.
При этом сделаем так, чтобы биндинг работал в обе стороны. Для этого надо в строке биндинга добавить символ = между @ и
Теперь при изменении текста в EditText, биндинг будет передавать новое значение в employee.name. А при включении\выключении чекбокса, биндинг будет передавать текущее состояние этого чекбокса в поле employee.enabled.
Т.е. изменения содержимого View будут отражены в Employee объекте, который мы передавали в биндинг. Если необходимо, можно использовать и Observable поля. С ними это тоже будет работать.
Кстати, если после передачи в биндинг вы нигде не храните у себя объект employee, то вы всегда можете получить его обратно методом binding.getEmployee().
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник
Быстрый старт 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);
Видим новый класс BR, в котором содержатся идентификаторы полей, чьи геттеры помечены атрибутом @Bindable . В Layout оставляем android:text=»@
ObservableFields
В пакете android.databinding есть классы, которые могут упростить нотификацию binder об изменении модели:
- Обёртки над элементарными типами
- ObservableField
- ObservableArrayMap
- ObservableArrayList
Попробуем изменить модель:
По коллекциям аналогично, единственное приведу пример обращения ко ключу к Map:
Из View в Model
Теперь попробуем взять новое имя из UI, привязав EditText к некоторой модели. Так как внутри EditText крутится Editable, то и привязать будет к
Изменю MainActivity:
А в разметку добавлю:
Вот тут возникает проблема, если привязать ObservableField к EditText, то всё будет работать только в сторону View. Как я понял, проблема в том, что Editable, который лежит внутри ObservableField, отличается от того, который лежит внутри EditText.
Если у кого есть идеи — делитесь.
Очень любопытно было увидеть библиотеку для поддержки Data Binding в Android от Google. В документации тоже нет информации про обратную связь данных, но я надеюсь на скорую её реализацию. После официального выхода стабильной версии можно будет посмотреть на интеграцию с JavaRX.
[ Оффициальная документация ]
[ Ссылка на мой простенький пример ]
Источник