410013796724260
• Webmoney
R335386147728
Z369087728698
Вернуться к «Разработчикам Android»
Пример использования Model-View-ViewModelНа странице рассмотрен пример использования Data Binding совместно с MVVM в приложении Android. Описание Data Binding и MVVM (Model-View-ViewModel) представлено на странице Data Binding Library в Android. Кратко отмечу, что использование Data Binding позволяет связать Java-объект с разметкой интерфейса layout (XML-файл). При этом некоторые свойства и методы Java-объекта можно непосредственно перенести в разметку XML-файла. MVVM — это шаблон определения архитектуры клиентских приложений, предложенный Джоном Госсманом (John Gossman) как альтернатива шаблонам MVC и MVP при использовании технологии связывания данных (Data Binding). Концепция MVVM связана с отделением логики представления данных от бизнес-логики путём вынесения её в отдельный класс для более четкого разграничения. Интерфейс примера![]() Чтобы было легче связать отдельные фрагменты описания кода примера с его конечной целью начнем с интерфейса представления. На скриншоте представлен интерфейс примера после старта в Android Studio. В примере создается 2 компонента типа TextView для отображения имени пользователя и его возраста. Ниже располагается кнопка. Интерфейс примера ничем не отличается от своего прототипа, в котором рассмотрено использование Data Binding. Бизнес-логика функционирования примера интуитивно понятна и примитивна. При старте в компонентах отображается имя и возраст одного пользователя. После нажатия на кнопку значение возраста age либо уменьшается на 3 единицы, если age > 18 , либо увеличивается на 2 единицы, если age < 18. Забегая вперед, отмечу, что значение изменяется в параметре user.age (Model), а ViewModel, отслеживая данное изменение, обновляет его в интерфейсе View. Описание кодаНиже представлен скриншот проекта/модуля databinding_mvvm в IDE Android Studio. ![]() В проекте определены следующие программные объекты, используемые в разработке примера : • strings.xml — ресурсный файл текстовых строк и шаблона представления возраста;• activity_main.xml — файл определения интерфейса (разметка); • User.java — класс описания пользователя; • MainActivity.java — главный модуль активности. Интерфейс примера на уровне среды разработки (IDE) определяет главный ресурсный файл activity_main.xml. В режиме исполнения примера главный модуль активности MainActivity.java формирует интерфейс и определяет бизнес-логику управления компонентами. Ресурсный файл strings.xml определяет текстовые значения интерфейсных компонентов. Класс User.java описывает объект пользователя. Необходимо также добавить, что в файле Gradle Scripts/build.gradle (app.databinding_mvvm) в секцию android добавлено определение dataBinding, как это приведено в описании библиотеки. Это необходимо выполнить, чтобы получить доступ к библиотеке Data Binding. На скриншоте раскрыта поддиректория модуля java (generated), в которой представлены генерируемые библиотекой Data Binding программные модули. Листинг strings.xmlРесурсный файл strings.xml создается автоматически средой Android Studio при формировании нового модуля/проекта. В модуле переопределен заголок (app_name) и добавлены строки определения текста. <resources> <string name="app_name">Data Binding and MVVM</string> <string name="button">Button</string> <string name="age_format">Возраст: %d</string> </resources> Заметка : строка age_format включает выражение, которое используется для определения возраста пользователя в компоненте View, т.е. текстовое значение компонента формируется динамически. activity_main.xmlНиже представлен листинг файла разметки activity_main.xml. На что следует обратить внимание в файле разметки :
Листинг activity_main.xml <?xml version="1.0" encoding="utf-8"?> <layout xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name = "user" type = "com.example.dbmvvm.User" /> <import type="android.view.View" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/userName" android:layout_width="160dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:text="@{user.name}" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"/> <TextView android:id="@+id/userAge" android:layout_width="160dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:text="@{@string/age_format(user.age)}" android:visibility="@{user.adult ? View.VISIBLE : View.INVISIBLE}" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf= "@+id/userName" /> <Button android:id="@+id/button" android:layout_width="160dp" android:layout_height="48dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:text="@string/button" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/userAge"/> </androidx.constraintlayout.widget.ConstraintLayout> </layout> Класс User.javaКласс User.java — это простой Java-объект, не унаследованный от какого-то специфического объекта. Класс содержит 2 поля, конструктор и методы Get/Set для обоих полей. Дополнительная логическая функция isAdult, имитирующая поля adult, возвращает значение true, если возраст меньше 18. Необходимо отметить, что весь объект/класс находится в зоне наблюдения (BaseObservable). О том, как можно наблюдать за отдельным полем класса/объекта описано здесь. Листинг User.java package com.example.dbmvvm; import androidx.annotation.NonNull; import androidx.databinding.BaseObservable; import androidx.databinding.Bindable; public class User extends BaseObservable { private int age; private String name; //--------------------------------- public User(int age, String name) { this.age = age; this.name = name; } //--------------------------------- @Bindable public int getAge() { return age; } //--------------------------------- public void setAge(int age) { this.age = age; notifyPropertyChanged(BR.age); notifyPropertyChanged(BR.adult); } //--------------------------------- @Bindable @NonNull public String getName() { return name; } //--------------------------------- public void setName(String name) { this.name = name; notifyPropertyChanged(BR.name); } //--------------------------------- @Bindable public boolean isAdult() { return age >= 18; } } Класс BR.javaВ разделе модуля/проекта появился один интересный класс BR.java, в котором содержатся идентификаторы полей, чьи методы Get помечены @Bindable. Класс BR подобен ресурсному R-классу и его можно использовать в java-коде (например, BR.age), вызывая метод notifyPropertyChanged. package androidx.databinding.library.baseAdapters; public class BR { public static final int _all = 0; public static final int adult = 1; public static final int age = 2; public static final int name = 3; public static final int user = 4; } MainActivity.javaФайл MainActivity.java наследует свойства активности AppCompatActivity, формирует интерфейс примера и определяет бизнес-логику кнопки подключением к ней слушателя события onClick. Особенности использования Data Binding в Java-коде :
Таким образом, используя объект связи binding типа ActivityMainBinding можно определить значения интерфейсных компонентов View и подключить к ним обработчики событий, а использование в приложении шаблона архитектуры MVVM позволяет связать данные (Model) и их представление в интерфейсе (View) через ViewModel. package com.example.dbmvvm; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import androidx.appcompat.app.AppCompatActivity; import com.example.dbmvvm.databinding.ActivityMainBinding; public class MainActivity extends AppCompatActivity { ActivityMainBinding binding; User user ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LayoutInflater inflater = getLayoutInflater(); binding = ActivityMainBinding.inflate(inflater); setContentView(binding.getRoot()); user = new User(25, "Alex"); binding.setUser(user); binding.button.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { int age; // Определение возраста if (user.getAge() < 18) age = user.getAge() + 2; else age = user.getAge() - 3; // Изменение возраста в объекте user.setAge(age); } } ); } } |