Ограничение доступа
Ролевой механизм
Загрузка модулей410013796724260
|
Вернуться к «Разработчикам 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);
}
}
);
}
}
|

