34
Moxy – реализация MVP под Android С щепоткой магии Шмаков Юрий [email protected]

Moxy – реализация MVP под Android. С щепоткой магии

Embed Size (px)

Citation preview

Page 1: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – реализация MVP под AndroidС щепоткой магии

Шмаков Юрий[email protected]

Page 2: Moxy – реализация MVP под Android. С щепоткой магии

Что такое MVPОсновные составляющие: Model, View и Presenter• Плюсы:• Код разбивается на мелкие, независимые кусочки• Сильно упрощается написание тестов к коду• Легко менять какую-то часть, не ломая при этом другую

•Минусы:• Кода становится больше• К этому подходу нужно привыкать• На данный момент не сильно распространённый

Page 3: Moxy – реализация MVP под Android. С щепоткой магии

MVP  в AndroidПозволяет снять метку God Object с Activity:• Полное управление GUI• Обработка взаимодействия с пользователем• Запуск асинхронных задач• Обработка результата асинхронной задачи

•Дополнительные хотелки:• View должна привязываться к уже имеющемуся Presenter

при смене конфигурации• View всегда обязана иметь актульаное состояния• Presenter должен уметь жить независимо от чего-то

Page 4: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – теорияView

ViewState

Presenter Model

Commands

Page 5: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – теорияView

ViewState

Presenter Model

Commands

Page 6: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – теорияView

ViewState

Presenter Model

Commands

Page 7: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – теорияView

ViewState

Presenter Model

Commands

Page 8: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – теория

ViewState

Presenter Model

Commands

View

Page 9: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – теория

ViewState

Presenter Model

Commands

View

Page 10: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – теория

ViewState

Presenter Model

Commands

View

Page 11: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – теория

ViewState

Presenter Model

Commands

View

View

Page 12: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – инструменты

Page 13: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – MvpPresenter• Содержит в себе часть бизнес-логики• Отвечает только за одну логическую единицу

бизнес-логики• Типизирован MvpView• Имеет полезные методы:• void attachView(View view) и void detachView(View view)• View getViewState()• void onFirstViewAttach()• boolean isInRestoreState(View view)

Page 14: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – MvpView и MvpViewState• MvpView описывает команды, которые Presenter

может передать во View• MvpViewState хранит команды, которые были

переданы во View• MvpViewState имеет метод void restoreState(View

view)• Чаще всего не придётся самостояетльно создавать

MvpViewState

Page 15: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – @InjectViewState• Применяется к классу MvpPresenter• Имеет три поведения:• Если указан параметр value, то будет использован

указанный ViewState• Если указан параметр view, то будет сгенерирован

ViewState для указанной View• Если никакой параметр не указан, то будет сгенерирован

ViewState для View, которой типизирован Presenter(опасайтесь типизированных View)

• Позволяет работать с методом View getViewState()

Page 16: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – StateStrategy• Управляет нахождением команды во ViewState• Имеет два callback-метод:• void beforeApply(currentState, incomingState)• void afterApply(currentState, incomingState)

• Указать стратегию можно аннотацией @StateStrategyType• @StateStrategyType можно применить:• Ко всему интерфейсу View• К конкретному методу интерфейса View

Page 17: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – MvpDelegate• Управляет жизненным циклом Presenter• Подставляет во View правильный экземпляр Presenter• Отвечает за привязку View к Presenter• Имеет несколько методов для получения состяния

View:• void onCreate(Bundle bundle), void onCreate() и void

onDestroy()• void onStart()• void onSaveInstanceState(Bundle outState)• void setParentDelegate(MvpDelegate delegate, String childId)

Page 18: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – @InjectPresenter• Применяется к Presenter-полям реализации View• Сообщает MvpDelegate, какой Presenter нужно

использовать• Может быть двух(с половиной) типов:• PresenterType.LOCAL• PresenterType.GLOBAL и PresenterType.WEAK

• В случае, если тип != PresenterType.LOCAL, MvpDelegate будет искать Presenter по одному из правил:• По статичному тэгу, указанному в параметре tag• Используя factory, сгенерирует тэг и сам Presenter, по

необходимости

Page 19: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – ModelСодержит в себе работу с данными:• Получение данных

• Из хранилища• Из интернате

• Хранение данных• Обработка данных

Самое подходящее место, чтобы разгуляться DI

Page 20: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – пример #1Задача: сделать экран авторизации•По нажатию на кнопку входа:• Показать диалог запроса• Начать асинхронный запрос авторизации

•После завершения асинхронного запроса авторизации:• Скрыть диалог прогресса• Если пришла ошибка, то показать диалог с ошибкой• Если авторизация прошла успешно, то перейти на

главный экран

Page 21: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – пример #1Задача: сделать экран авторизации

Решение:•Сделать SignInView•Сделать SignInPresenter•Сделать SignInActivity

Page 22: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – пример #1@StateStrategyType(AddToEndSingleStrategy.class)public interface SignInView extends MvpView{ void toggleProgress(boolean show);

void showError(Exception exception);

void hideError();

void onSignIn();}

public class SignInActivity extends MvpActivity implements SignInView{ @InjectPresenter SignInPresenter mSignInPresenter;

...

Page 23: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – пример #1@InjectViewStatepublic class SignInPresenter extends MvpPresenter<SignInView>{ @Inject Repository mRepository;

public SignInPresenter() { WagamamaApplication.getAppComponent().inject(this); }

public void auth(final String login, final String password) { getViewState().hideError(); getViewState().toggleProgress(true); ↓↓↓

↓↓↓ mRepository.authentication().signIn(login, password) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<AuthenticateData>() { @Override public void onCompleted() { getViewState().toggleProgress(false); getViewState().onSignIn(); }

@Override public void onError(Throwable e) { getViewState().toggleProgress(false); getViewState().showError(new Exception(e)); } });

Page 24: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – пример #2Задача: сделать аудиоплеер•В приложении есть список треков• Текущий трек выделяется и имеет кнопку play/pause

•В приложении есть фрагмент, в котором отображается текущий трек, его состяние и кнопки play/pause и prev/next•Приложение отображает notification с отображением текущего трека, его состяние и кнопок play/pause и prev/next

Page 25: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – пример #2Задача: сделать аудиоплеер

Решение:•Сделать PlayerView•Сделать PlayerPresenter•Сделать PlaylistAdapter•Сделать PlayerFragment•Сделать PlayerService

Page 26: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – пример #2public interface PlayerView extends MvpView{ String PLAYER_STATE = "playerState";

@StateStrategyType(SingleStateStrategy.class) void setCurrentTrack(TrackInfo track);

@StateStrategyType(value = PlayerStateStrategy.class, tag = PLAYER_STATE) void playTrack();

@StateStrategyType(value = PlayerStateStrategy.class, tag = PLAYER_STATE) void pauseTrack();}

Page 27: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – пример #2public class PlayerStateStrategy implements StateStrategy{ @Override public <View extends MvpView> void beforeApply(List<Pair<ViewCommand<View>, Object>> currentState, Pair<ViewCommand<View>, Object> incomingState) { for (Pair<ViewCommand<View>, Object> viewCommand : currentState) { if (viewCommand.first.getTag().equals(PlayerView.PLAYER_STATE)) { currentState.remove(viewCommand); break; } }

currentState.add(incomingState); }

@Override public <View extends MvpView> void afterApply(List<Pair<ViewCommand<View>, Object>> currentState, Pair<ViewCommand<View>, Object> incomingState) { }}

Page 28: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – пример #2public class PlayerPresenter extends MvpPresenter<PlayerView>{ public static final String TAG = "player";

public PlayerPresenter() { super(); PlayerApp.get().getBus().register(this); }

@Subscribe public void playTrack(PlayTrackEvent event) { playTrack(event.getTrack()); }

public void playTrack(TrackInfo trackInfo) { getViewState().setCurrentTrack(trackInfo); getViewState().playTrack(); } ↓↓↓

↓↓↓ public void playTrack() { getViewState().playTrack(); }

public void pauseTrack() { getViewState().pauseTrack(); }

@Override public void onDestroy() { super.onDestroy(); PlayerApp.get().getBus().unregister(this); }}

Page 29: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – пример #2public class PlaylistAdapter extends BaseAdapter implements PlayerView{ @InjectPresenter(type = PresenterType.WEAK, tag = PlayerPresenter.TAG) PlayerPresenter mPlayerPresenter;

public PlaylistAdapter(MvpDelegate<?> parentDelegate) { MvpDelegate<PlaylistAdapter> delegate = new MvpDelegate<>(this); delegate.setParentDelegate(parentDelegate, ""); delegate.onCreate(); } ...

public class MainActivity extends MvpActivity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);

PlaylistAdapter adapter = new PlaylistAdapter(getMvpDelegate()); ...

Page 30: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – пример #2public class PlayerService extends Service implements PlayerView{ @InjectPresenter(type = PresenterType.WEAK, tag = PlayerPresenter.TAG) PlayerPresenter mPlayerPresenter;

private MvpDelegate<PlayerService> mDelegate;

@Override public void onCreate() { super.onCreate(); mDelegate = new MvpDelegate<>(this); mDelegate.onCreate(null); mDelegate.onStart(); } ... @Override public void onDestroy() { super.onDestroy();

mDelegate.onDestroy(); ...

Page 31: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – пример #2public class PlayerFragment extends MvpFragment implements PlayerView{ @InjectPresenter(type = PresenterType.WEAK, tag = PlayerPresenter.TAG) PlayerPresenter mPlayerPresenter; ...

Page 32: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – конкурентыглавный конкурент– одинMosby с неудобным ViewState

Page 33: Moxy – реализация MVP под Android. С щепоткой магии

Moxy – итого• Что имеем:

• Решены проблемы с жизненным циклом• Всегда отображается актуальное состояние бизнес-логики• Code generation

• Важные советы:• Не меняйте View командой из View • Добавляйте и удаляйте элементы View только через Presenter• Если не компилится, внимательно вчитайтесь в описание

ошибки• Используйте DI для связки Presenter↔Model• MVP != инструмент

Page 34: Moxy – реализация MVP под Android. С щепоткой магии

На почитать• Moxy — реализация MVP под Android с щепоткой магии• Android Application Architecture (Android Dev Summit 2015)• Android Testing Codelab• Nucleus• Mosby• Old Mosby• STINSON'S PLAYBOOK FOR MOSBY • Android Reactive MVP: практика• Andrtoid Clean Architecture • Алексей Макаров. Speaker Clean Architecture и MVP • Mosby issues 85