Антон Валюх - Использование паттерна mvvm в android

Post on 20-Mar-2017

1.990 Views

Category:

Technology

3 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Спикер:

Тема:

Антон Валюх

Использование паттерна MVVM в Android

MVP

MVP (Model-View-Presenter) — шаблон проектирования, производный от MVC, который был разработан в основном для построения пользовательского интерфейса.

Используется для облегчения автоматического модульного тестирования и улучшения разделения логики от отображения. Основные принципы работы с шаблоном MVP, были подробно проанализированы в статье Мартина Фаулера «GUI Architectures» (2006).

http://martinfowler.com/eaaDev/uiArchs.html

MVP

View Presenter Model

user events updates model

state-change eventupdates view

View это интерфейс пользователя, который отображает данные и выполняет маршрутизацию пользовательских команд (событий) в Presenter.

Presenter управляет данными (Model) и представлением (View). Он извлекает данные из модели и форматирует их для отображения во View.

Model предоставляет данные для пользовательского интерфейса.

MVP

public interface SomeScreenView { void startLoading(); void stopLoading(); void mapDataItems(final Collection<DataItem> items);}

MVP позволяет создавать абстракцию представления. Для этого необходимо выделить интерфейс представления с определенным набором свойств и методов. 

MVP

public class SomeScreenPresenter extends Presenter { private SomeScreenView mView; public void setView(SomeScreenView view) { mView = view; } @Override public void initialize() { mView.startLoading(); mView.mapDataItems(...); mView.stopLoading(); }}

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

Presenter взаимодействует с View путем использования специального интерфейса, который описывает абстракцию этого View.

MVP

@EActivity(R.layout.activity_some_screen)public class SomeScreenActivity extends Activity implements SomeScreenView { private SomeScreenPresenter mPresenter; @ViewById(R.id.drawer_layout) protected ProgressBar mProgressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mPresenter = new SomeScreenPresenter(this); mPresenter.initialize(); }}

View взаимодействует напрямую с Presenter-ом, путем вызова соответствующих функций или событий экземпляра Presenter.

MVVM

MVVM

View ViewModel Model

UI eventsModel change

events

Update

ViewModel data

Property hanged events

Read

MVVM позволяет связывать элементы View со свойствами и событиями ViewModel. ViewModel — это абстракция представления. Свойства View совпадают со свойствами ViewModel/Model. При этом ViewModel не имеет ссылки на интерфейс представления.

Изменение состояния View-модели автоматически изменяет представление и наоборот. Для этого используется механизм связывания данных (Bindings).

Для MVVM характерна двухсторонняя коммуникация с представлением.

MVVM

• RoboBinding

• ngAndroid

• Bindroid

• Android Data Binding

RoboBinding

Представляет собой MVVM фреймворк для платформы Android.

• позволяет легко осуществить привязку (binding) атрибутов для любых пользовательских компонентов, сторонних компонентов или виджетов для Android. Как результат позволяет «выкинуть» много «ненужного кода» за счет использования бинов.

• не уменьшает производительность за счет использования генерации кода вместо рефлексии.

RoboBinding - установка

apply plugin: 'com.android.application'apply plugin: 'com.neenbedankt.android-apt'

apt("org.robobinding:codegen:$robobindingVersion") { exclude group: 'com.google.android', module: 'android'}

compile("org.robobinding:robobinding:$robobindingVersion") { exclude group: 'com.google.android', module: 'android'}

buildscript { dependencies { classpath 'com.android.tools.build:gradle:xxx' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4' }}

RoboBinding - ViewModel

@PresentationModelpublic class SomeScreenViewModel implements HasPresentationModelmChangeSupport {

private PresentationModelChangeSupport mChangeSupport; private String mUserFirstName; private String mUserLastName;

public SomeScreenViewModel() { mChangeSupport = new PresentationModelChangeSupport(this); }

public String getUserFirstName() { return mUserFirstName; } public String getUserLastName() { return mUserLastName; } public String getUserFullName() { return mUserFirstName + " " + mUserLastName; }

public void setUserFirstName(String userFirstName){ mUserFirstName = userFirstName; } public void setUserLastName(String userLastName){ mUserLastName = userLastName; } public void updateUser() { mChangeSupport.firePropertyChange("userFullName"); } @Override public PresentationModelChangeSupport getPresentationModelmChangeSupport() { return mChangeSupport; }}

RoboBinding – Layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:bind="http://robobinding.org/android" android:orientation="vertical">

<TextView …… bind:text="{userFullName}"/> <EditText …… bind:text="${userFirstName}"/>

<EditText …… bind:text="${userLastName}"/> <Button …… bind:onClick="updateUser"/>

</LinearLayout>

RoboBinding - Activity

public class SomeScreenActivity extends Activity {

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SomeScreenViewModel presentationModel = new SomeScreenViewModel();

View rootView = Binders.inflateAndBindWithoutPreInitializingViews(this, R.layout.activity_some_screen, presentationModel);

setContentView(rootView); }

}

RoboBinding

Достоинства:- двунаправленное связывание- генерация кода- поддержка списков

Недостатки:- проблемы с библиотекой AppCompat- нет поддержки RecyclerView

ngAndroid

Основан на идеях JavaScript-фреймворка – AngularJS.

ngAndroid - установка

compile 'com.github.davityle:ngandroid:0.0.4'

ngAndroid - Model

public class Model { private String mUserFirstName; private String mUserLastName; private String mUserFullName; public String getUserFirstName() { return mUserFirstName; } public String getUserLastName() { return mUserLastName; } public String getUserFullName() { return mUserFullName; }

public void setUserFirstName(String userFirstName){ mUserFirstName = userFirstName; } public void setUserLastName(String userLastname){ mUserLastName = userLastname; } public void setUserFullName(String userFullName) { mUserFullName = userFullName; }}

ngAndroid - Layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:ng="http://schemas.android.com/apk/res-auto" android:orientation="vertical">

<TextView …… ng:ngModel="model.userFullName" <EditText …… ng:ngModel="model.userFirstName"/> <EditText …… ng:ngModel="model.userLastName"/>

<Button …… ng:ngClick="updateUser()"/> </LinearLayout>

ngAndroid - Activity

@NgScopepublic class SomeScreenActivity extends Activity {

@NgModel SomeScreenViewModel mScreenViewModel;

private final NgAndroid mNg = NgAndroid.getInstance();

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mNg.setContentView(this, R.layout.activity_some_screen); } protected void updateUser(){ String firstName = mScreenViewModel.getUserFirstName(); String lastName = mScreenViewModel.getUserLastName(); mScreenViewModel.setUserFullName(firstName + " " + lastName); }}

ngAndroid – а так же….

Поддерживаемые на данный момент angular директивы:

• NgModel• NgClick• NgLongClick• NgChange• NgDisabled• NgInvisible• NgGone• NgBlur• NgFocus

ngAndroid

Достоинства:- двунаправленное связывание- проект на стадии активной разработки

Недостатки:- нет поддержки списков / RecyclerView- используется рефлексия (обещают перейти на

генерацию кода)- проект на стадии активной разработки, поэтому

достаточно сырой

Bindroid

Bindroid реализация шаблона MVVM для Android приложений. Представляет собой библиотеку с открытым исходным кодом, основной целью которой является упрощение связывания UI и данных. В ее основе лежит шаблон Наблюдатель (Observer) для работы с моделями а так же набор методов для быстрого связывания этих объектов и интерфейсов пользователя.

Bindroid - Model

public class SomeScreenViewModel { private TrackableField<String> mUserFirstName = new TrackableField<String>(); private TrackableField<String> mUserLastName = new TrackableField<String>(); private TrackableField<String> mUserFullName = new TrackableField<String>("Here could be your advertising."); public String getUserFirstName() { return mUserFirstName.get(); } public void setUserFirstName(String firstName) { mUserFirstName.set(firstName);} public String getUserLastName() { return mUserLastName.get(); } public void setUserLastName(String lastName) { mUserLastName.set(lastName); } public String getUserFullName() { return mUserFullName.get(); } public void setUserFullName(String fullName) { mUserFullName.set(fullName); }}

Bindroid - Layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical">

<TextView …… android:id="@+id/text_user_fullname" <EditText …… android:id="@+id/edit_user_firstname"/> <EditText …… android:id="@+id/edit_user_lastname"/>

<Button …… android:onClick="updateUser"/> </LinearLayout>

Bindroid - Activity

public class SomeScreenActivity extends Activity {

SomeScreenViewModel mScreenViewModel = new SomeScreenViewModel();

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_some_screen); UiBinder.bind(new EditTextTextProperty(this.findViewById( R.id.edit_user_firstname)), mScreenViewModel, "userFirstName", BindingMode.TWO_WAY);

UiBinder.bind(new EditTextTextProperty(this.findViewById( R.id.edit_user_lastname)), mScreenViewModel, "userLastName", BindingMode.TWO_WAY);

UiBinder.bind(new TextViewTextProperty(this.findViewById(R.id.text_user_fullname)), mScreenViewModel, "userFullName", BindingMode.TWO_WAY);

} public void updateUser(View v){ String firstName = mScreenViewModel.getUserFirstName(); String lastName = mScreenViewModel.getUserLastName(); mScreenViewModel.setUserFullName(firstName + " " + lastName); }}

Bindroid

Достоинства:- двунаправленное связывание- поддерживает работу с библиотекой AppCompat

Недостатки:- нет поддержки генерации кода- нет проверки во временя компиляции- слишком много кода для связывания

Android Data Binding

- анонсирована на Google IO 15;- создана Google;- пока доступна только как beta.

Android Data Binding - установка

apply plugin: 'com.android.databinding'

dependencies { classpath 'com.android.tools.build:gradle:1.3.0-beta2' classpath 'com.android.databinding:dataBinder:1.0-rc0'}

Android Data Binding - Model

public class User { private String mFirstName; private String mLastName; private String mFullName;

public User(String firstName, String lastName) { mFirstName = firstName; mLastName = lastName; } public String getFirstName() { return mUserFirstName; } public String getLastName() { return mLastName; } public String getFullName() { return mFullName; } public void setFirstName(String userFirstName) { mUserFirstName = userFirstName; } public void setLastName(String userLastname){ mUserLastName = userLastname; } public void setFullName(String userFullName) { mUserFullName = userFullName; }

public void updateUser(View v){ mFullName = mFirstName + " " + mLastName; }}

Android Data Binding - Layout

<layout xmlns:android="http://schemas.android.com/apk/res/android">

<data> <variable name="user" type="com.example.User"/> </data> <LinearLayout ……>

<TextView …… android:text="{user.fullNameName}"/> <EditText …… android:text="@{user.firstName}"/> <EditText …… android:text="@{user.lastName}"/>

<Button …… android:onClick="updateUser"/>

</LinearLayout></layout>

Android Data Binding - Activity

public class SomeScreenActivity extends Activity {

private User mUser = new User("Anton", "Valiuh");

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);

binding.setUser(mUser); }}

Android Data Binding – а так же….

• Язык выражений android:text="@{String.format("Hello %s",viewModel.field )}" android:onClick="@{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}“

• Импорты <import type="android.view.View" alias="SomeAlias"/>

... android:visibility="@{user.isAdult ? SomeAlias.VISIBLE : SomeAlias.GONE}“

• Поддержка ресурсов android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}“

• Поддержка коллекций android:text="@{list[index]}" android:text="@{map[`firstName`}“

• Возможность создавать кастомные бины.

И много чего еще.

Android Data Binding

Достоинства:- официальная библиотеки от Google- генерация кода- проверка во время компиляции- простота в использовании и расширении- новый Android стандарт

Недостатки:- нет поддержки двунаправленного связывания (пока еще)- нет поддержки IDE (пока еще)- много ложных ошибок в Android Studio (но все компилируется и запуска)

Ваши вопросы?

Благодарю за внимание!

top related