В этом уроке знакомимся с Data Binding.
Полный список уроков курса:
- Урок 1. Lifecycle
- Урок 2. LiveData
- Урок 3. LiveData. Дополнительные возможности
- Урок 4. ViewModel
- Урок 5. Room. Основы
- Урок 6. Room. Entity
- Урок 7. Room. Insert, Update, Delete, Transaction
- Урок 8. Room. Query
- Урок 9. Room. RxJava
- Урок 10. Room. Запрос из нескольких таблиц. Relation
- Урок 11. Room. Type converter
- Урок 12. Room. Миграция версий базы данных
- Урок 13. Room. Тестирование
- Урок 14. Paging Library. Основы
- Урок 15. Paging Library. PagedList и DataSource. Placeholders.
- Урок 16. Paging Library. LivePagedListBuilder. BoundaryCallback.
- Урок 17. Paging Library. Виды DataSource
- Урок 18. Android Data Binding. Основы
- Урок 19. Android Data Binding. Код в layout. Доступ к View
- Урок 20. Android Data Binding. Обработка событий
- Урок 21. Android Data Binding. Observable поля. Двусторонний биндинг.
- Урок 22. Android Data Binding. Adapter. Conversion.
- Урок 23. Android Data Binding. Использование с include, ViewStub и RecyclerView.
- Урок 24. Navigation Architecture Component. Введение
- Урок 25. Navigation. Передача данных. Type-safe аргументы.
- Урок 26. Navigation. Параметры навигации
- Урок 27. Navigation. NavigationUI.
- Урок 28. Navigation. Вложенный граф. Global Action. Deep Link.
- Урок 29. WorkManager. Введение
- Урок 30. WorkManager. Критерии запуска задачи.
- Урок 31. WorkManager. Последовательность выполнения задач.
- Урок 32. WorkManager. Передача и получение данных
- Урок 33. Практика. О чем это будет.
- Урок 34. Практика. TodoApp. Список задач.
- Урок 35. Практика. TodoApp. Просмотр задачи
В build.gradle файл модуля в секции android необходимо включить Data Binding:
android { .... dataBinding { enabled = true } }
Правильно произносить байндинг, но биндинг звучит проще - буду использовать его.
Data Binding поможет организовать работу с View так, чтобы нам не пришлось писать кучу методов findViewById, setText, setOnClickListener и т.п. Давайте рассмотрим простой пример.
Есть класс Employee, который содержит в себе данные о работнике
public class Employee { public Employee(long id, String name, String address) { this.id = id; this.name = name; this.address = address; } public long id; public String name; public String address; }
поля: id, имя и адрес.
Мы хотим вывести имя и адрес работника на экран main_activity.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/address" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
Несложная задача. Для этого мы обычно пишем методы findViewById и setText. Тут все понятно.
Давайте рассмотрим, как это же можно сделать с помощью Data Binding.
Вносим изменения в main_activity.xml:
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="employee" type="ru.startandroid.application.data.Employee" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{employee.name}" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{employee.address}" /> </LinearLayout> </layout>
Корневым элементом теперь является <layout>, а LinearLayout сместился внутрь него.
В секции data мы объявляем переменную с именем employee. Ее тип - ранее рассмотренный класс Employee. Теперь мы можем использовать эту переменную в атрибутах вьюшек этого layout. В первом TextView, в атрибуте text мы используем employee.name, а в втором TextView - employee.address.
Обратите внимание, что мы не указываем id для View. В этом нет необходимости.
Как вы понимаете, нам остается лишь передать объект Employee в этот layout. И значения этого объекта будут подставлены в соответствующие TextView.
Это делается следующим образом.
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Employee employee = new Employee(1, "John Smith", "London"); MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity); binding.setEmployee(employee); } }
Сначала создаем 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:
binding.setEmployee(employee);
Или можно вызывать метод invalidateAll:
binding.invalidateAll();
Биндинг считает новые данные с ранее полученного объекта Employee.
Поля в Employee в этом примере я сделал public. Но вы можете сделать их private и создать для них public get методы.
Возможно, использование биндинга для пары TextView кажется бессмысленным. Но когда таких TextView десятки, то биндинг может избавить вас от написания кучи кода.
Кроме того, мы рассмотрели совсем простой случай использования биндинга. Но его возможности гораздо шире. Например, можно сделать так, чтобы при передаче в атрибут ImageView ссылки на картинку, биндинг запускал Picasso для загрузки этой картинки и помещал результат в ImageView. Или биндинг может сам отслеживать изменения в объекте с данными (в примере выше - это Employee ) и обновлять экран без каких-либо дополнительных методов.
Эти возможности мы рассмотрим в следующих уроках.
Присоединяйтесь к нам в Telegram:
- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance
- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня