SlideShare una empresa de Scribd logo
1 de 49
Descargar para leer sin conexión
Как я научился не волноваться и
полюбил Android-MVP
Никита Баришок
План
Почему MVP?
Android-MVP: главное
Android-MVP: реальность
О взаимодействии между V и P
Итоги
2
Почему MVP?
3
Почему MVP?
Важные характеристики системы:
-  понятность кода
-  расширяемость
-  готовность к изменениям
-  тестируемость
4
Почему MVP?
Важные характеристики системы:
-  понятность кода
-  расширяемость
-  готовность к изменениям
-  тестируемость
Это всё НЕ о традиционном подходе!
5
Почему MVP?
MVP / MVVM(С) / ... фундаментально об одном и том же:
Добиваться повышения качества системы за счет разбиения её на слои с
четко выраженными обязанностями и абстрагирования этих слоев друг от
друга.
/* If you put ten software architects into a room and have
them discuss what the Model-View-Controller pattern is, you
will end up with twelve different opinions.(с) */
6
Почему MVP?
MVP / MVVM(C) / ... фундаментально об одном и том же:
Добиваться повышения качества системы за счет разбиения её на слои с
четко выраженными обязанностями и абстрагирования этих слоев друг от
друга.
MVP:
+  легче поддается тестированию
-  требует больше кода
/* If you put ten software architects into a room and have
them discuss what the Model-View-Controller pattern is, you
will end up with twelve different opinions.(с) */
7
Android-MVP: теория
8
Android-MVP: описание MVP
Смысл:
отделить представление от логики
Для Android:
помогает решить проблему, когда Activity выступает в роли God Object
9
Android-MVP: описание MVP
VIEW PRESENTER MODEL
оповестить о
событии
запросить
данные
обновить UI получить данные
View максимально прост и пассивен
Model включает в себя слой получения данных и бизнес-логики
Presenter получает данные из Model, трансформирует их, отдает во View; решает, что делает
View.
10
Android-MVP: MVP + Clean architecture
VIEW PRESENTER INTERACTOR REPOSITORY
ENTITY1
ENTITY2
VIEWMODEL
V P M
DOMAIN LAYER DATA LAYER
11
Android-MVP: практика
12
Android-MVP: model
public interface Api {
@GET("weather")
Observable<WeatherResponse> get(@Query("APPID") String key, @Query("q") String q);
}
REPOSITORY
ENTITY1
ENTITY2
13
Android-MVP: model
public interface Api {
@GET("weather")
Observable<WeatherResponse> get(@Query("APPID") String key, @Query("q") String q);
}
public class WeatherResponse {
Coord coord;
List<Weather> weather;
String base;
Main main;
Wind wind;
Clouds clouds;
double dt;
Sys sys;
int id;
String name;
int cod;
}
14
REPOSITORY
ENTITY1
ENTITY2
Android-MVP: model
public interface Api {
@GET("weather")
Observable<WeatherResponse> get(@Query("APPID") String key, @Query("q") String q);
}
public class WeatherResponse {
Coord coord;
List<Weather> weather;
String base;
Main main;
Wind wind;
Clouds clouds;
double dt;
Sys sys;
int id;
String name;
int cod;
}
public class Main {
double temp;
double pressure;
double humidity;
double tempMin;
double tempMax;
}
15
public class Wind {
double speed;
double deg;
}
...
REPOSITORY
ENTITY1
ENTITY2
Android-MVP: model
public interface WeatherRepository {
Observable<WeatherResponse> getWeather(String city);
}
16
REPOSITORY
ENTITY1
ENTITY2
Android-MVP: model
public interface WeatherRepository {
Observable<WeatherResponse> getWeather(String city);
}
public class WeatherRetrofitRepository implements WeatherRepository {
Api api;
public WeatherRetrofitRepository(Api api) {
this.api = api;
}
@Override
public Observable<WeatherResponse> getWeather(String city) {
return api.get(BuildConfig.WEATHER_API_KEY, city);
}
}
17
REPOSITORY
ENTITY1
ENTITY2
Android-MVP: model
public interface GetWeatherInMoscowInteractor {
Observable<WeatherResponse> get();
}
public class GetWeatherInMoscowUseCase implements GetWeatherInMoscowInteractor {
private final WeatherRepository repository;
public GetWeatherInMoscowUseCase(WeatherRepository repo) {
repository = repo;
}
@Override
public Observable<WeatherResponse> get() {
return repository.getWeather("Moscow");
}
}
INTERACTOR
18
Android-MVP. Практика: Model
public interface GetWeatherInMoscowInteractor {
Observable<WeatherResponse> get();
}
public class GetWeatherInMoscowUseCase implements GetWeatherInMoscowInteractor {
private final WeatherRepository repository;
private final CacheManager cacheManager;
public GetWeatherInMoscowUseCase(WeatherRepository repo, CacheManager cacheMan) {
repository = repo;
cacheManager = cacheMan;
}
@Override
public Observable<WeatherResponse> get() {
return repository
.getWeather("Moscow")
.doOnNext(weather -> {cacheManager.put(weather);});
}
}
19
INTERACTOR
Android-MVP: presenter
public abstract class Presenter<V> {
private volatile V view;
public void attachView(V v) { view = v; }
public void detachView() { view = null; }
public void onCreate(Bundle arguments, Bundle savedInstanceState) { }
public void onSaveInstanceState(Bundle bundle) { }
public void onDestroy() { }
}
PRESENTER
VIEWMODEL
20
public class WeatherPresenterImpl extends WeatherPresenter {
private GetWeatherInMoscowInteractor getWeather;
private WeatherMapper mapper;
@Override
public void loadWeather() {
getWeather.get()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(weather -> updateUi(mapper.map(weather)),
throwable -> showError(WeatherError.GENERAL)));
}
}
public abstract class WeatherPresenter extends Presenter<WeatherView> {
public abstract void loadWeather();
}
Android-MVP: presenter
21
PRESENTER
VIEWMODEL
Android-MVP: view
public interface WeatherView extends LCEView<WeatherViewModel,WeatherError> {
enum WeatherError { GENERAL }
}
public interface LCEView<D, E> {
void showLoading();
void hideLoading();
void setData(D data);
void showContent();
void showError(E error);
}
public class WeatherViewModel implements Parcelable {
int temperature;
}
VIEW
22
Android-MVP: view
public class WeatherFragment extends Fragment implements WeatherView {
@Override
public void showLoading() {
// показать индикатор загрузки
}
...
}
23
VIEW
Android-MVP: view
public class WeatherFragment extends Fragment implements WeatherView {
WeatherPresenter presenter = new WeatherPresenterImpl(new GetWeatherInMoscowUseCase(
new WeatherRetrofitRepository(RetrofitHelper.getWeatherApi())), new WeatherMapperImpl());
@Override
public void showLoading() {
// показать индикатор загрузки
}
...
}
24
VIEW
Android-MVP: view
public class WeatherFragment
extends ComponentManagerFragment<WeatherComponent, WeatherView>
implements WeatherView {
@Override
protected WeatherComponent createComponent() {
return DaggerWeatherComponent
.builder()
.appComponent(...)
.build();
}
@Override
public void onViewCreated(final View view, final Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getPresenter().loadWeather();
}
...
}
25
VIEW
Android-MVP: реальность
26
Android-MVP: реальность
public class WeatherFragment
extends ComponentManagerFragment<WeatherComponent, WeatherView>
implements WeatherView {
...
@Override
public void onViewCreated(final View view, final Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getPresenter().loadWeather();
}
...
}
27
Android-MVP: реальность (2)
28
Android-MVP: реальность (2)
29
Android-MVP: реальность (2)
30
Android-MVP: реальность (2)
31
public class WeatherPresenterImpl extends WeatherPresenter {
@Override
public void loadWeather() {
getWeather.get()
.subscribe(weather -> {
if (view != null) { updateUi(mMapper.map(weather)); }
}, throwable -> {
if (view != null) { showError(WeatherView.WeatherError.GENERAL); }
}));
}
}
Android-MVP: реальность (2)
32
Слой между View и Presenter:
-  (Со стороны Presenter) это View без жизненного цикла (~POJO)
-  (Со стороны View) это Presenter с возможностью восстановить состояние у
View при необходимости
Android-MVP: о взаимодействии V и P
33
public class WeatherPresenterImpl extends WeatherPresenter { }
public class WeatherFragment implements WeatherView { }
public class WeatherCommunicationBus extends WeatherPresenter
implements WeatherView {
// view
@Override
public void showLoading() {
if (view != null) {
view.showLoading();
}
}
...
// presenter
@Override
public void loadWeather() {
presenter.loadWeather();
}
...
}
Android-MVP: о взаимодействии V и P
34
public class WeatherCommunicationBus extends WeatherPresenter implements WeatherView {
public WeatherCommunicationBus(WeatherPresenter presenter) {
mPresenter = presenter;
mPresenter.attachView(this);
}
...
@Override
public void onDestroy() {
mPresenter.detachView();
mPresenter.onDestroy();
}
...
}
Android-MVP: о взаимодействии V и P
35
public class WeatherViewState implements ViewState<WeatherView>, Parcelable {
private final static int STATE_UNINITIALIZED = -1;
private final static int STATE_DEFAULT = 0;
private final static int STATE_SHOW_LOADING = 1;
private final static int STATE_SHOW_ERROR = 2;
private int mCurrentState = 0;
private WeatherView.WeatherError mError;
private WeatherViewModel mModel;
public void setStateShowLoading() {
mCurrentState = STATE_SHOW_LOADING;
}
...
public void apply(WeatherView view) {
switch (mCurrentState) {
case STATE_SHOW_LOADING:
view.showLoading();
break;
...
}
Android-MVP: о взаимодействии V и P
36
public abstract class MvpLceViewStateFragment extends MvpLceFragment {
...
@Override public void showContent() {
super.showContent();
viewState.setStateShowContent(getData());
}
@Override public void showError(Throwable e, boolean pullToRefresh) {
super.showError(e, pullToRefresh);
viewState.setStateShowError(e, pullToRefresh);
}
...
}
Android-MVP: о взаимодействии V и P
37
38
1
39
2
40
3
41
public class WeatherCommunicationBus extends WeatherPresenter implements WeatherView {
private final WeatherPresenter presenter;
private WeatherView view;
private WeatherViewState viewState;
public WeatherCommunicationBus(WeatherPresenter presenter) {
presenter = presenter;
viewState = new WeatherViewState();
presenter.attachView(this);
}
@Override
public void showLoading() {
viewState.setStateShowLoading();
if (view != null) { mView.showLoading(); }
}
@Override
public void attachView(WeatherView view) {
view = view;
viewState.apply(view);
}
}
Android-MVP: о взаимодействии V и P
42
43
1
44
2
45
1
46
Итоги
Android-MVP:
-  Много кода
+  Код намного более понятный и гибкий
+  Качество приложения выше
+  Скорость разработки выше
+  UX лучше (если не теряется состояние)
47
Ресурсы
GIT:
https://github.com/nbarishok/RxMvpAndroid
Medium:
https://medium.com/@nbarishok/on-communication-between-v-and-p-in-android-
mvp-16caf773e1a5#.6mhrjpkw4
Dagger 2 + custom scopes:
https://guides.codepath.com/android/Dependency-Injection-with-Dagger-2
http://frogermcs.github.io/dependency-injection-with-dagger-2-custom-scopes/
DI & Сохранение presenter’a:
http://blog.bradcampbell.nz/mvp-presenters-that-survive-configuration-changes-part-2/
48
Самое время для вопросов
Контакты:
nikita_b@abbyy.com
https://twitter.com/onemanparty_
49

Más contenido relacionado

La actualidad más candente

Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, Controllers
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, ControllersШкола-студия разработки приложений для iOS. 2 лекция. MVC, View, Controllers
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, Controllers
Глеб Тарасов
 
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOS
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOSКурсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOS
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOS
Глеб Тарасов
 
Разработка Web-приложений на Angular JS. Архитектурные семинары Softengi
Разработка Web-приложений на Angular JS. Архитектурные семинары SoftengiРазработка Web-приложений на Angular JS. Архитектурные семинары Softengi
Разработка Web-приложений на Angular JS. Архитектурные семинары Softengi
Softengi
 
Библиотека Google Closure Java Script
Библиотека Google Closure Java ScriptБиблиотека Google Closure Java Script
Библиотека Google Closure Java Script
Volodymyr Forfutdinov
 

La actualidad más candente (20)

Модульная структура
Модульная структураМодульная структура
Модульная структура
 
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, Controllers
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, ControllersШкола-студия разработки приложений для iOS. 2 лекция. MVC, View, Controllers
Школа-студия разработки приложений для iOS. 2 лекция. MVC, View, Controllers
 
Антон Валюх - Использование паттерна Mvvm в android
Антон Валюх - Использование паттерна Mvvm в androidАнтон Валюх - Использование паттерна Mvvm в android
Антон Валюх - Использование паттерна Mvvm в android
 
Build a VR Pawn with Unreal Engine Luis Cataldi Russian
Build a VR Pawn with Unreal Engine   Luis Cataldi RussianBuild a VR Pawn with Unreal Engine   Luis Cataldi Russian
Build a VR Pawn with Unreal Engine Luis Cataldi Russian
 
Как приручить реактивное программирование в XAML приложениях
Как приручить реактивное программирование в XAML приложенияхКак приручить реактивное программирование в XAML приложениях
Как приручить реактивное программирование в XAML приложениях
 
Как приручить реактивное программирование
Как приручить реактивное программированиеКак приручить реактивное программирование
Как приручить реактивное программирование
 
Gwt jug basic
Gwt jug basicGwt jug basic
Gwt jug basic
 
Олексій Стульніков “WinAppDriver – автоматизація Desktop ніколи не була такою...
Олексій Стульніков “WinAppDriver – автоматизація Desktop ніколи не була такою...Олексій Стульніков “WinAppDriver – автоматизація Desktop ніколи не була такою...
Олексій Стульніков “WinAppDriver – автоматизація Desktop ніколи не була такою...
 
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOS
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOSКурсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOS
Курсы по мобильной разработке. 2 лекция. Построение интерфейсов в iOS
 
Vue.js - реактивный фронтенд фреймворк для людей
Vue.js - реактивный фронтенд фреймворк для людейVue.js - реактивный фронтенд фреймворк для людей
Vue.js - реактивный фронтенд фреймворк для людей
 
Рендеринг может больше: vue.js vs React, Андрей Солодовников
Рендеринг может больше: vue.js vs React, Андрей СолодовниковРендеринг может больше: vue.js vs React, Андрей Солодовников
Рендеринг может больше: vue.js vs React, Андрей Солодовников
 
C# Web. Занятие 11.
C# Web. Занятие 11.C# Web. Занятие 11.
C# Web. Занятие 11.
 
#3 "Webpack и Vue.JS: Создание больших приложений и их расширение" Кирилл Кай...
#3 "Webpack и Vue.JS: Создание больших приложений и их расширение" Кирилл Кай...#3 "Webpack и Vue.JS: Создание больших приложений и их расширение" Кирилл Кай...
#3 "Webpack и Vue.JS: Создание больших приложений и их расширение" Кирилл Кай...
 
Где кончается react native? / Павел Кондратенко (Rambler&Co)
Где кончается react native? / Павел Кондратенко (Rambler&Co)Где кончается react native? / Павел Кондратенко (Rambler&Co)
Где кончается react native? / Павел Кондратенко (Rambler&Co)
 
AndroidMVPHelper
AndroidMVPHelperAndroidMVPHelper
AndroidMVPHelper
 
Разработка Web-приложений на Angular JS. Архитектурные семинары Softengi
Разработка Web-приложений на Angular JS. Архитектурные семинары SoftengiРазработка Web-приложений на Angular JS. Архитектурные семинары Softengi
Разработка Web-приложений на Angular JS. Архитектурные семинары Softengi
 
Введение в Android-разработку (Lecture 06 – basics)
Введение в Android-разработку (Lecture 06 – basics)Введение в Android-разработку (Lecture 06 – basics)
Введение в Android-разработку (Lecture 06 – basics)
 
Системы автоматизированной сборки (Lecture 05 – gradle)
Системы автоматизированной сборки (Lecture 05 – gradle)Системы автоматизированной сборки (Lecture 05 – gradle)
Системы автоматизированной сборки (Lecture 05 – gradle)
 
Библиотека Google Closure Java Script
Библиотека Google Closure Java ScriptБиблиотека Google Closure Java Script
Библиотека Google Closure Java Script
 
Лекция 1. Введение в Android.
Лекция 1. Введение в Android.Лекция 1. Введение в Android.
Лекция 1. Введение в Android.
 

Destacado

Destacado (10)

«Взломать за 60 секунд», Артем Кулаков, Redmadrobot
«Взломать за 60 секунд», Артем Кулаков, Redmadrobot«Взломать за 60 секунд», Артем Кулаков, Redmadrobot
«Взломать за 60 секунд», Артем Кулаков, Redmadrobot
 
«JMM в Android», Максим Ефимов, Redmadrobot
«JMM в Android», Максим Ефимов, Redmadrobot«JMM в Android», Максим Ефимов, Redmadrobot
«JMM в Android», Максим Ефимов, Redmadrobot
 
Droidcon Moscow 2015. Clean Architecture и MVP. Алексей Макаров - Zvooq
Droidcon Moscow 2015. Clean Architecture и MVP. Алексей Макаров - ZvooqDroidcon Moscow 2015. Clean Architecture и MVP. Алексей Макаров - Zvooq
Droidcon Moscow 2015. Clean Architecture и MVP. Алексей Макаров - Zvooq
 
Tecnologia constructiva con sal
Tecnologia constructiva con salTecnologia constructiva con sal
Tecnologia constructiva con sal
 
Lifted Short Film Spotting Notes
Lifted Short Film Spotting NotesLifted Short Film Spotting Notes
Lifted Short Film Spotting Notes
 
Getting things done intro
Getting things done introGetting things done intro
Getting things done intro
 
Infarto al Miocardio sin Elevacion de ST
Infarto al Miocardio sin Elevacion de STInfarto al Miocardio sin Elevacion de ST
Infarto al Miocardio sin Elevacion de ST
 
【待更新】匯流 N 法是否支持「網路中立性」討論會
【待更新】匯流 N 法是否支持「網路中立性」討論會【待更新】匯流 N 法是否支持「網路中立性」討論會
【待更新】匯流 N 法是否支持「網路中立性」討論會
 
ESEM PROYECTO COLOMBIA
ESEM PROYECTO COLOMBIAESEM PROYECTO COLOMBIA
ESEM PROYECTO COLOMBIA
 
Clean architecture on Android
Clean architecture on AndroidClean architecture on Android
Clean architecture on Android
 

Similar a «Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYY

UAFPUG6 - PureMVC
UAFPUG6 - PureMVCUAFPUG6 - PureMVC
UAFPUG6 - PureMVC
mandrew182
 
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha Dmitry
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha DmitryUafpug 8 Presentation Puremvc Papervision Gallery Kuriksha Dmitry
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha Dmitry
Max Rozdobudko
 
Android Development Course in HSE lecture #1
Android Development Course in HSE lecture #1Android Development Course in HSE lecture #1
Android Development Course in HSE lecture #1
Empatika
 

Similar a «Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYY (20)

Uneta 17.04.15 Bondarenko - What's NEW in Windows 10 SDK?
Uneta 17.04.15 Bondarenko - What's NEW in Windows 10 SDK?Uneta 17.04.15 Bondarenko - What's NEW in Windows 10 SDK?
Uneta 17.04.15 Bondarenko - What's NEW in Windows 10 SDK?
 
Windows 10 SDK
Windows 10 SDKWindows 10 SDK
Windows 10 SDK
 
Tdd php
Tdd phpTdd php
Tdd php
 
UAFPUG6 - PureMVC
UAFPUG6 - PureMVCUAFPUG6 - PureMVC
UAFPUG6 - PureMVC
 
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha Dmitry
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha DmitryUafpug 8 Presentation Puremvc Papervision Gallery Kuriksha Dmitry
Uafpug 8 Presentation Puremvc Papervision Gallery Kuriksha Dmitry
 
PureMVC and Papervision
PureMVC and PapervisionPureMVC and Papervision
PureMVC and Papervision
 
Java осень 2014 занятие 5
Java осень 2014 занятие 5Java осень 2014 занятие 5
Java осень 2014 занятие 5
 
Как навести порядок в коде вашего web-приложения, Андрей Чебукин
Как навести порядок в коде вашего web-приложения, Андрей Чебукин Как навести порядок в коде вашего web-приложения, Андрей Чебукин
Как навести порядок в коде вашего web-приложения, Андрей Чебукин
 
"Погружение в Robolectric" Дмитрий Костырев (Avito)
"Погружение в Robolectric"  Дмитрий Костырев (Avito)"Погружение в Robolectric"  Дмитрий Костырев (Avito)
"Погружение в Robolectric" Дмитрий Костырев (Avito)
 
PureMVC в картинках - часть 1
PureMVC в картинках - часть 1PureMVC в картинках - часть 1
PureMVC в картинках - часть 1
 
Viper - чистая архитектура iOS-приложения (И. Чирков)
Viper - чистая архитектура iOS-приложения (И. Чирков)Viper - чистая архитектура iOS-приложения (И. Чирков)
Viper - чистая архитектура iOS-приложения (И. Чирков)
 
Валерий Чугреев, ИСЭРТ РАН — Архитектура MVC в контексте web-разработки — про...
Валерий Чугреев, ИСЭРТ РАН — Архитектура MVC в контексте web-разработки — про...Валерий Чугреев, ИСЭРТ РАН — Архитектура MVC в контексте web-разработки — про...
Валерий Чугреев, ИСЭРТ РАН — Архитектура MVC в контексте web-разработки — про...
 
Лекция Android
Лекция AndroidЛекция Android
Лекция Android
 
Денис Неклюдов. Держи свое приложение на волне новинок. РИФ-Воронеж 2016
Денис Неклюдов. Держи свое приложение на волне новинок. РИФ-Воронеж 2016Денис Неклюдов. Держи свое приложение на волне новинок. РИФ-Воронеж 2016
Денис Неклюдов. Держи свое приложение на волне новинок. РИФ-Воронеж 2016
 
MVVM в WinForms – DevExpress Way (теория и практика)
MVVM в WinForms – DevExpress Way (теория и практика)MVVM в WinForms – DevExpress Way (теория и практика)
MVVM в WinForms – DevExpress Way (теория и практика)
 
Deep Dive in Magento DI
Deep Dive in Magento DIDeep Dive in Magento DI
Deep Dive in Magento DI
 
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
 
Паттерны проектирования
Паттерны проектированияПаттерны проектирования
Паттерны проектирования
 
Android - 05 - Android basics
Android - 05 - Android basicsAndroid - 05 - Android basics
Android - 05 - Android basics
 
Android Development Course in HSE lecture #1
Android Development Course in HSE lecture #1Android Development Course in HSE lecture #1
Android Development Course in HSE lecture #1
 

Más de Mail.ru Group

AMP для электронной почты, Сергей Пешков
AMP для электронной почты, Сергей ПешковAMP для электронной почты, Сергей Пешков
AMP для электронной почты, Сергей Пешков
Mail.ru Group
 

Más de Mail.ru Group (20)

Автоматизация без тест-инженеров по автоматизации, Мария Терехина и Владислав...
Автоматизация без тест-инженеров по автоматизации, Мария Терехина и Владислав...Автоматизация без тест-инженеров по автоматизации, Мария Терехина и Владислав...
Автоматизация без тест-инженеров по автоматизации, Мария Терехина и Владислав...
 
BDD для фронтенда. Автоматизация тестирования с Cucumber, Cypress и Jenkins, ...
BDD для фронтенда. Автоматизация тестирования с Cucumber, Cypress и Jenkins, ...BDD для фронтенда. Автоматизация тестирования с Cucumber, Cypress и Jenkins, ...
BDD для фронтенда. Автоматизация тестирования с Cucumber, Cypress и Jenkins, ...
 
Другая сторона баг-баунти-программ: как это выглядит изнутри, Владимир Дубровин
Другая сторона баг-баунти-программ: как это выглядит изнутри, Владимир ДубровинДругая сторона баг-баунти-программ: как это выглядит изнутри, Владимир Дубровин
Другая сторона баг-баунти-программ: как это выглядит изнутри, Владимир Дубровин
 
Использование Fiddler и Charles при тестировании фронтенда проекта pulse.mail...
Использование Fiddler и Charles при тестировании фронтенда проекта pulse.mail...Использование Fiddler и Charles при тестировании фронтенда проекта pulse.mail...
Использование Fiddler и Charles при тестировании фронтенда проекта pulse.mail...
 
Управление инцидентами в Почте Mail.ru, Антон Викторов
Управление инцидентами в Почте Mail.ru, Антон ВикторовУправление инцидентами в Почте Mail.ru, Антон Викторов
Управление инцидентами в Почте Mail.ru, Антон Викторов
 
DAST в CI/CD, Ольга Свиридова
DAST в CI/CD, Ольга СвиридоваDAST в CI/CD, Ольга Свиридова
DAST в CI/CD, Ольга Свиридова
 
Почему вам стоит использовать свой велосипед и почему не стоит Александр Бел...
Почему вам стоит использовать свой велосипед и почему не стоит  Александр Бел...Почему вам стоит использовать свой велосипед и почему не стоит  Александр Бел...
Почему вам стоит использовать свой велосипед и почему не стоит Александр Бел...
 
CV в пайплайне распознавания ценников товаров: трюки и хитрости Николай Масл...
CV в пайплайне распознавания ценников товаров: трюки и хитрости  Николай Масл...CV в пайплайне распознавания ценников товаров: трюки и хитрости  Николай Масл...
CV в пайплайне распознавания ценников товаров: трюки и хитрости Николай Масл...
 
RAPIDS: ускоряем Pandas и scikit-learn на GPU Павел Клеменков, NVidia
RAPIDS: ускоряем Pandas и scikit-learn на GPU  Павел Клеменков, NVidiaRAPIDS: ускоряем Pandas и scikit-learn на GPU  Павел Клеменков, NVidia
RAPIDS: ускоряем Pandas и scikit-learn на GPU Павел Клеменков, NVidia
 
WebAuthn в реальной жизни, Анатолий Остапенко
WebAuthn в реальной жизни, Анатолий ОстапенкоWebAuthn в реальной жизни, Анатолий Остапенко
WebAuthn в реальной жизни, Анатолий Остапенко
 
AMP для электронной почты, Сергей Пешков
AMP для электронной почты, Сергей ПешковAMP для электронной почты, Сергей Пешков
AMP для электронной почты, Сергей Пешков
 
Как мы захотели TWA и сделали его без мобильных разработчиков, Данила Стрелков
Как мы захотели TWA и сделали его без мобильных разработчиков, Данила СтрелковКак мы захотели TWA и сделали его без мобильных разработчиков, Данила Стрелков
Как мы захотели TWA и сделали его без мобильных разработчиков, Данила Стрелков
 
Кейсы использования PWA для партнерских предложений в Delivery Club, Никита Б...
Кейсы использования PWA для партнерских предложений в Delivery Club, Никита Б...Кейсы использования PWA для партнерских предложений в Delivery Club, Никита Б...
Кейсы использования PWA для партнерских предложений в Delivery Club, Никита Б...
 
Метапрограммирование: строим конечный автомат, Сергей Федоров, Яндекс.Такси
Метапрограммирование: строим конечный автомат, Сергей Федоров, Яндекс.ТаксиМетапрограммирование: строим конечный автомат, Сергей Федоров, Яндекс.Такси
Метапрограммирование: строим конечный автомат, Сергей Федоров, Яндекс.Такси
 
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru GroupКак не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
 
Этика искусственного интеллекта, Александр Кармаев (AI Journey)
Этика искусственного интеллекта, Александр Кармаев (AI Journey)Этика искусственного интеллекта, Александр Кармаев (AI Journey)
Этика искусственного интеллекта, Александр Кармаев (AI Journey)
 
Нейро-машинный перевод в вопросно-ответных системах, Федор Федоренко (AI Jour...
Нейро-машинный перевод в вопросно-ответных системах, Федор Федоренко (AI Jour...Нейро-машинный перевод в вопросно-ответных системах, Федор Федоренко (AI Jour...
Нейро-машинный перевод в вопросно-ответных системах, Федор Федоренко (AI Jour...
 
Конвергенция технологий как тренд развития искусственного интеллекта, Владими...
Конвергенция технологий как тренд развития искусственного интеллекта, Владими...Конвергенция технологий как тренд развития искусственного интеллекта, Владими...
Конвергенция технологий как тренд развития искусственного интеллекта, Владими...
 
Обзор трендов рекомендательных систем от Пульса, Андрей Мурашев (AI Journey)
Обзор трендов рекомендательных систем от Пульса, Андрей Мурашев (AI Journey)Обзор трендов рекомендательных систем от Пульса, Андрей Мурашев (AI Journey)
Обзор трендов рекомендательных систем от Пульса, Андрей Мурашев (AI Journey)
 
Мир глазами нейросетей, Данила Байгушев, Александр Сноркин ()
Мир глазами нейросетей, Данила Байгушев, Александр Сноркин ()Мир глазами нейросетей, Данила Байгушев, Александр Сноркин ()
Мир глазами нейросетей, Данила Байгушев, Александр Сноркин ()
 

«Как я научился не волноваться и полюбил Android-MVP», Никита Бартишок, ABBYY

  • 1. Как я научился не волноваться и полюбил Android-MVP Никита Баришок
  • 2. План Почему MVP? Android-MVP: главное Android-MVP: реальность О взаимодействии между V и P Итоги 2
  • 4. Почему MVP? Важные характеристики системы: -  понятность кода -  расширяемость -  готовность к изменениям -  тестируемость 4
  • 5. Почему MVP? Важные характеристики системы: -  понятность кода -  расширяемость -  готовность к изменениям -  тестируемость Это всё НЕ о традиционном подходе! 5
  • 6. Почему MVP? MVP / MVVM(С) / ... фундаментально об одном и том же: Добиваться повышения качества системы за счет разбиения её на слои с четко выраженными обязанностями и абстрагирования этих слоев друг от друга. /* If you put ten software architects into a room and have them discuss what the Model-View-Controller pattern is, you will end up with twelve different opinions.(с) */ 6
  • 7. Почему MVP? MVP / MVVM(C) / ... фундаментально об одном и том же: Добиваться повышения качества системы за счет разбиения её на слои с четко выраженными обязанностями и абстрагирования этих слоев друг от друга. MVP: +  легче поддается тестированию -  требует больше кода /* If you put ten software architects into a room and have them discuss what the Model-View-Controller pattern is, you will end up with twelve different opinions.(с) */ 7
  • 9. Android-MVP: описание MVP Смысл: отделить представление от логики Для Android: помогает решить проблему, когда Activity выступает в роли God Object 9
  • 10. Android-MVP: описание MVP VIEW PRESENTER MODEL оповестить о событии запросить данные обновить UI получить данные View максимально прост и пассивен Model включает в себя слой получения данных и бизнес-логики Presenter получает данные из Model, трансформирует их, отдает во View; решает, что делает View. 10
  • 11. Android-MVP: MVP + Clean architecture VIEW PRESENTER INTERACTOR REPOSITORY ENTITY1 ENTITY2 VIEWMODEL V P M DOMAIN LAYER DATA LAYER 11
  • 13. Android-MVP: model public interface Api { @GET("weather") Observable<WeatherResponse> get(@Query("APPID") String key, @Query("q") String q); } REPOSITORY ENTITY1 ENTITY2 13
  • 14. Android-MVP: model public interface Api { @GET("weather") Observable<WeatherResponse> get(@Query("APPID") String key, @Query("q") String q); } public class WeatherResponse { Coord coord; List<Weather> weather; String base; Main main; Wind wind; Clouds clouds; double dt; Sys sys; int id; String name; int cod; } 14 REPOSITORY ENTITY1 ENTITY2
  • 15. Android-MVP: model public interface Api { @GET("weather") Observable<WeatherResponse> get(@Query("APPID") String key, @Query("q") String q); } public class WeatherResponse { Coord coord; List<Weather> weather; String base; Main main; Wind wind; Clouds clouds; double dt; Sys sys; int id; String name; int cod; } public class Main { double temp; double pressure; double humidity; double tempMin; double tempMax; } 15 public class Wind { double speed; double deg; } ... REPOSITORY ENTITY1 ENTITY2
  • 16. Android-MVP: model public interface WeatherRepository { Observable<WeatherResponse> getWeather(String city); } 16 REPOSITORY ENTITY1 ENTITY2
  • 17. Android-MVP: model public interface WeatherRepository { Observable<WeatherResponse> getWeather(String city); } public class WeatherRetrofitRepository implements WeatherRepository { Api api; public WeatherRetrofitRepository(Api api) { this.api = api; } @Override public Observable<WeatherResponse> getWeather(String city) { return api.get(BuildConfig.WEATHER_API_KEY, city); } } 17 REPOSITORY ENTITY1 ENTITY2
  • 18. Android-MVP: model public interface GetWeatherInMoscowInteractor { Observable<WeatherResponse> get(); } public class GetWeatherInMoscowUseCase implements GetWeatherInMoscowInteractor { private final WeatherRepository repository; public GetWeatherInMoscowUseCase(WeatherRepository repo) { repository = repo; } @Override public Observable<WeatherResponse> get() { return repository.getWeather("Moscow"); } } INTERACTOR 18
  • 19. Android-MVP. Практика: Model public interface GetWeatherInMoscowInteractor { Observable<WeatherResponse> get(); } public class GetWeatherInMoscowUseCase implements GetWeatherInMoscowInteractor { private final WeatherRepository repository; private final CacheManager cacheManager; public GetWeatherInMoscowUseCase(WeatherRepository repo, CacheManager cacheMan) { repository = repo; cacheManager = cacheMan; } @Override public Observable<WeatherResponse> get() { return repository .getWeather("Moscow") .doOnNext(weather -> {cacheManager.put(weather);}); } } 19 INTERACTOR
  • 20. Android-MVP: presenter public abstract class Presenter<V> { private volatile V view; public void attachView(V v) { view = v; } public void detachView() { view = null; } public void onCreate(Bundle arguments, Bundle savedInstanceState) { } public void onSaveInstanceState(Bundle bundle) { } public void onDestroy() { } } PRESENTER VIEWMODEL 20
  • 21. public class WeatherPresenterImpl extends WeatherPresenter { private GetWeatherInMoscowInteractor getWeather; private WeatherMapper mapper; @Override public void loadWeather() { getWeather.get() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(weather -> updateUi(mapper.map(weather)), throwable -> showError(WeatherError.GENERAL))); } } public abstract class WeatherPresenter extends Presenter<WeatherView> { public abstract void loadWeather(); } Android-MVP: presenter 21 PRESENTER VIEWMODEL
  • 22. Android-MVP: view public interface WeatherView extends LCEView<WeatherViewModel,WeatherError> { enum WeatherError { GENERAL } } public interface LCEView<D, E> { void showLoading(); void hideLoading(); void setData(D data); void showContent(); void showError(E error); } public class WeatherViewModel implements Parcelable { int temperature; } VIEW 22
  • 23. Android-MVP: view public class WeatherFragment extends Fragment implements WeatherView { @Override public void showLoading() { // показать индикатор загрузки } ... } 23 VIEW
  • 24. Android-MVP: view public class WeatherFragment extends Fragment implements WeatherView { WeatherPresenter presenter = new WeatherPresenterImpl(new GetWeatherInMoscowUseCase( new WeatherRetrofitRepository(RetrofitHelper.getWeatherApi())), new WeatherMapperImpl()); @Override public void showLoading() { // показать индикатор загрузки } ... } 24 VIEW
  • 25. Android-MVP: view public class WeatherFragment extends ComponentManagerFragment<WeatherComponent, WeatherView> implements WeatherView { @Override protected WeatherComponent createComponent() { return DaggerWeatherComponent .builder() .appComponent(...) .build(); } @Override public void onViewCreated(final View view, final Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); getPresenter().loadWeather(); } ... } 25 VIEW
  • 27. Android-MVP: реальность public class WeatherFragment extends ComponentManagerFragment<WeatherComponent, WeatherView> implements WeatherView { ... @Override public void onViewCreated(final View view, final Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); getPresenter().loadWeather(); } ... } 27
  • 32. public class WeatherPresenterImpl extends WeatherPresenter { @Override public void loadWeather() { getWeather.get() .subscribe(weather -> { if (view != null) { updateUi(mMapper.map(weather)); } }, throwable -> { if (view != null) { showError(WeatherView.WeatherError.GENERAL); } })); } } Android-MVP: реальность (2) 32
  • 33. Слой между View и Presenter: -  (Со стороны Presenter) это View без жизненного цикла (~POJO) -  (Со стороны View) это Presenter с возможностью восстановить состояние у View при необходимости Android-MVP: о взаимодействии V и P 33
  • 34. public class WeatherPresenterImpl extends WeatherPresenter { } public class WeatherFragment implements WeatherView { } public class WeatherCommunicationBus extends WeatherPresenter implements WeatherView { // view @Override public void showLoading() { if (view != null) { view.showLoading(); } } ... // presenter @Override public void loadWeather() { presenter.loadWeather(); } ... } Android-MVP: о взаимодействии V и P 34
  • 35. public class WeatherCommunicationBus extends WeatherPresenter implements WeatherView { public WeatherCommunicationBus(WeatherPresenter presenter) { mPresenter = presenter; mPresenter.attachView(this); } ... @Override public void onDestroy() { mPresenter.detachView(); mPresenter.onDestroy(); } ... } Android-MVP: о взаимодействии V и P 35
  • 36. public class WeatherViewState implements ViewState<WeatherView>, Parcelable { private final static int STATE_UNINITIALIZED = -1; private final static int STATE_DEFAULT = 0; private final static int STATE_SHOW_LOADING = 1; private final static int STATE_SHOW_ERROR = 2; private int mCurrentState = 0; private WeatherView.WeatherError mError; private WeatherViewModel mModel; public void setStateShowLoading() { mCurrentState = STATE_SHOW_LOADING; } ... public void apply(WeatherView view) { switch (mCurrentState) { case STATE_SHOW_LOADING: view.showLoading(); break; ... } Android-MVP: о взаимодействии V и P 36
  • 37. public abstract class MvpLceViewStateFragment extends MvpLceFragment { ... @Override public void showContent() { super.showContent(); viewState.setStateShowContent(getData()); } @Override public void showError(Throwable e, boolean pullToRefresh) { super.showError(e, pullToRefresh); viewState.setStateShowError(e, pullToRefresh); } ... } Android-MVP: о взаимодействии V и P 37
  • 38. 38
  • 39. 1 39
  • 40. 2 40
  • 41. 3 41
  • 42. public class WeatherCommunicationBus extends WeatherPresenter implements WeatherView { private final WeatherPresenter presenter; private WeatherView view; private WeatherViewState viewState; public WeatherCommunicationBus(WeatherPresenter presenter) { presenter = presenter; viewState = new WeatherViewState(); presenter.attachView(this); } @Override public void showLoading() { viewState.setStateShowLoading(); if (view != null) { mView.showLoading(); } } @Override public void attachView(WeatherView view) { view = view; viewState.apply(view); } } Android-MVP: о взаимодействии V и P 42
  • 43. 43
  • 44. 1 44
  • 45. 2 45
  • 46. 1 46
  • 47. Итоги Android-MVP: -  Много кода +  Код намного более понятный и гибкий +  Качество приложения выше +  Скорость разработки выше +  UX лучше (если не теряется состояние) 47
  • 48. Ресурсы GIT: https://github.com/nbarishok/RxMvpAndroid Medium: https://medium.com/@nbarishok/on-communication-between-v-and-p-in-android- mvp-16caf773e1a5#.6mhrjpkw4 Dagger 2 + custom scopes: https://guides.codepath.com/android/Dependency-Injection-with-Dagger-2 http://frogermcs.github.io/dependency-injection-with-dagger-2-custom-scopes/ DI & Сохранение presenter’a: http://blog.bradcampbell.nz/mvp-presenters-that-survive-configuration-changes-part-2/ 48
  • 49. Самое время для вопросов Контакты: nikita_b@abbyy.com https://twitter.com/onemanparty_ 49