SlideShare a Scribd company logo
1 of 73
Download to read offline
Навигация
без боли и слез
Константин Цховребов
Android Team Leader
Первый большой проект на MVP
В теории все прекрасно!
Первый большой проект на MVP
В теории все прекрасно!
Первый большой проект на MVP
На практике встречаешь ANDROID
Навигация в андроид приложении
Навигация в андроид приложении
●  Переход между экранами
Навигация в андроид приложении
●  Переход между экранами
●  Экраны сменяются в некотором контейнере
Навигация в андроид приложении
●  Переход между экранами
●  Экраны сменяются в некотором контейнере
●  Для совершения перехода нужен Context
А что если Fragment
сделать презентером?
А что если Fragment
сделать презентером?
1.  Lifecycle
А что если Fragment
сделать презентером?
1.  Lifecycle
2.  Нужен универсальный подход
(Activity/Fragment/View)
А что если Fragment
сделать презентером?
1.  Lifecycle
2.  Нужен универсальный подход
(Activity/Fragment/View)
3.  Context (и другие классы)
Mosby (http://hannesdorfmann.com/mosby/)
public interface LoginView extends MvpView {
public void showLoginForm();
public void showError();
public void showLoading();
public void loginSuccessful();
}
	
public class LoginFragment … implements
LoginView {
…
// Called when login was successful
@Override public void loginSuccessful() {
getActivity().finish();
}
…
}
Готовые решения
Flow
(https://github.com/square/flow)
Conductor
(https://github.com/bluelinelabs/Conductor)
Требования к идеальной навигации
Требования к идеальной навигации
●  прямой доступ из презентера
Требования к идеальной навигации
●  прямой доступ из презентера
●  не завязана на фрагменты
Требования к идеальной навигации
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
Требования к идеальной навигации
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
Требования к идеальной навигации
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
Требования к идеальной навигации
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
●  приспособлена для тестов
Требования к идеальной навигации
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
●  приспособлена для тестов
●  не зависит от жизненного цикла!
//TODO:
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
●  приспособлена для тестов
●  не зависит от жизненного цикла!
Это реальный проект!
Команды переходов
Команды переходов
Forward(String screenKey, Object transitionData);
Команды переходов
Forward(String screenKey, Object transitionData);
Back();
Команды переходов
Forward(String screenKey, Object transitionData);
Back();
BackTo(String screenKey);
Команды переходов
Forward(String screenKey, Object transitionData);
Back();
BackTo(String screenKey);
Replace(String screenKey, Object transitionData);
SystemMessage
SystemMessage(String message);
Navigator
public interface Navigator {
void applyCommand(Command command);
}
Navigator
public interface Navigator {
void applyCommand(Command command);
}
public class MainActivity extends Activity {
private Navigator navigator = new Navigator() {
@Override
public void applyCommand(Command command) {
...
}
}
}
//TODO:
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
●  приспособлена для тестов
●  не зависит от жизненного цикла!
//TODO:
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
●  приспособлена для тестов
●  не зависит от жизненного цикла!
✓
public class Presenter {
@Inject
Navigator navigator;
private void next() {
navigator.applyCommand(new Forward(“Some screen”));
}
}
//TODO:
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
●  приспособлена для тестов
●  не зависит от жизненного цикла!
✓
//TODO:
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
●  приспособлена для тестов
●  не зависит от жизненного цикла!
✓
✓
public class Presenter {
@Inject
Navigator navigator;
private void authError() {
navigator.applyCommand(new BackTo(null));
navigator.applyCommand(new Replace("Login screen", null));
navigator.applyCommand(new SystemMessage("Token expired!"));
}
}
Router
public class Router extends BaseRouter {
void newRootScreenWithMessage(String screenKey, Object data, String message) {...}
}
Router
public class Router extends BaseRouter {
void newRootScreenWithMessage(String screenKey, Object data, String message) {...}
}
public class Presenter {
@Inject
Router router;
private void authError() {
router.newRootScreenWithMessage("Login screen", null, "Token expired!");
}
}
//TODO:
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
●  приспособлена для тестов
●  не зависит от жизненного цикла!
✓
✓
//TODO:
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
●  приспособлена для тестов
●  не зависит от жизненного цикла!
✓
✓
✓
public class Router extends BaseRouter {
private Navigator navigator;
public void setNavigator(Navigator navigator) {
this.navigator = navigator;
}
public void removeNavigator() {
this.navigator = null;
}
public void newRootScreenWithMessage(String screenKey, Object data, String message) {
if (navigator != null) {
navigator.applyCommand(new BackTo(null));
navigator.applyCommand(new Replace("Login screen", null));
navigator.applyCommand(new SystemMessage("Token expired!"));
}
}
}
public class MainActivity extends Activity {
@Override
protected void onResume() {
super.onResume();
router.setNavigator(navigator);
}
@Override
protected void onPause() {
super.onPause();
router.removeNavigator();
}
}
Presenter View
load()
ViewPresenter
load()
request()
Presenter
request()
View
Presenter
request() response()
View
Presenter
Router
request() response()
View
Presenter
RouterImpl
Command
Queue
request() response()
View
ViewPresenter
RouterImpl
Command
Queue
request() response()
//TODO:
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
●  приспособлена для тестов
●  не зависит от жизненного цикла!
✓
✓
✓
//TODO:
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
●  приспособлена для тестов
●  не зависит от жизненного цикла!
✓
✓
✓
✓
Unit тестирование
@Test
public void someTest() throws Exception {
Router mockRouter = mock(Router.class);
Presenter presenter = new Presenter();
presenter.onNextButtonClicked();
verify(mockRouter, times(1)).navigateTo(
eq("Some screen"),
argument.capture()
);
}
//TODO:
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
●  приспособлена для тестов
●  не зависит от жизненного цикла!
✓
✓
✓
✓
//TODO:
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
●  приспособлена для тестов
●  не зависит от жизненного цикла!
✓
✓
✓
✓
✓
Расширение возможностей
●  в большинстве случаев достаточно добавить
метод в Router и реализовать его с помощью
Command
●  реже необходимо создать новую Command
//TODO:
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
●  приспособлена для тестов
●  не зависит от жизненного цикла!
✓
✓
✓
✓
✓
//TODO:
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
●  приспособлена для тестов
●  не зависит от жизненного цикла!
✓
✓
✓
✓
✓
✓
//TODO:
●  прямой доступ из презентера
●  не завязана на фрагменты
●  не фреймворк
●  короткие вызовы
●  легка в расширении
●  приспособлена для тестов
●  не зависит от жизненного цикла!
✓
✓
✓
✓
✓
✓
✓
Cicerone
Чичероне - (устар.) гид для иностранцев
https://github.com/terrakok/Cicerone
repositories {
maven {
url 'https://dl.bintray.com/terrakok/terramaven/'
}
}
dependencies {
//Cicerone
compile 'ru.terrakok.cicerone:cicerone:1.0'
}
Для кого мы ее создали?
Для кого мы ее создали?
Для себя :)
Для кого мы ее создали?
Почему она может пригодиться вам?
Для себя :)
Для кого мы ее создали?
●  В приложении нелинейная навигация
Почему она может пригодиться вам?
Для себя :)
Для кого мы ее создали?
●  В приложении нелинейная навигация
●  Отделение логики от отображения
Почему она может пригодиться вам?
Для себя :)
Для кого мы ее создали?
●  В приложении нелинейная навигация
●  Отделение логики от отображения
●  Сохранение вызовов навигации после
возвращения к приложению
Почему она может пригодиться вам?
Для себя :)
Возможности Cicerone
public class Router extends BaseRouter {
void navigateTo(String screenKey, Object data);
void newScreenChain(String screenKey, Object data);
void newRootScreen(String screenKey, Object data);
void replaceScreen(String screenKey, Object data);
void backTo(String screenKey);
void exit();
void exitWithMessage(String message);
void showSystemMessage(String message);
}
public abstract class FragmentNavigator implements Navigator {}
Спасибо за внимание! Вопросы?
email: terrakok@mobileup.ru
telegram: @terrakok
https://github.com/terrakok/Cicerone

More Related Content

What's hot

Мастер класс- Maven + Jenkins
Мастер класс- Maven + JenkinsМастер класс- Maven + Jenkins
Мастер класс- Maven + Jenkins
Valentin Fedoskin
 
XP.Party (iOS) - unit tests frameworks overview
XP.Party (iOS) - unit tests frameworks overviewXP.Party (iOS) - unit tests frameworks overview
XP.Party (iOS) - unit tests frameworks overview
Anton Katkov
 
Maven как средство сборки проекта
Maven как средство сборки проектаMaven как средство сборки проекта
Maven как средство сборки проекта
Yova Stoika
 
Илья Евлампиев - Нагрузочное тестирование веб-приложений с помощью The Grinder
Илья Евлампиев - Нагрузочное тестирование веб-приложений с помощью The GrinderИлья Евлампиев - Нагрузочное тестирование веб-приложений с помощью The Grinder
Илья Евлампиев - Нагрузочное тестирование веб-приложений с помощью The Grinder
SQALab
 

What's hot (20)

Мастер класс- Maven + Jenkins
Мастер класс- Maven + JenkinsМастер класс- Maven + Jenkins
Мастер класс- Maven + Jenkins
 
BDD girls Battle: Cucumber VS. JBehave
BDD girls Battle: Cucumber VS. JBehaveBDD girls Battle: Cucumber VS. JBehave
BDD girls Battle: Cucumber VS. JBehave
 
XP.Party (iOS) - unit tests frameworks overview
XP.Party (iOS) - unit tests frameworks overviewXP.Party (iOS) - unit tests frameworks overview
XP.Party (iOS) - unit tests frameworks overview
 
Презентация Git-flow (на русском)
Презентация Git-flow (на русском)Презентация Git-flow (на русском)
Презентация Git-flow (на русском)
 
Python Development process in Yandex
Python Development process in YandexPython Development process in Yandex
Python Development process in Yandex
 
Gradle in Enterprise, Is it possible?
Gradle in Enterprise, Is it possible?Gradle in Enterprise, Is it possible?
Gradle in Enterprise, Is it possible?
 
Transitive dependencies
Transitive dependenciesTransitive dependencies
Transitive dependencies
 
Инструментация среды исполнения в арсенале тестировщика
Инструментация среды исполнения в арсенале тестировщикаИнструментация среды исполнения в арсенале тестировщика
Инструментация среды исполнения в арсенале тестировщика
 
Артём Ерошенко «Рецепт приготовления облачных тестингов»
Артём Ерошенко «Рецепт приготовления облачных тестингов»Артём Ерошенко «Рецепт приготовления облачных тестингов»
Артём Ерошенко «Рецепт приготовления облачных тестингов»
 
Cистемы автоматической сборки проектов (Полина Фоминых)
Cистемы автоматической сборки проектов (Полина Фоминых)Cистемы автоматической сборки проектов (Полина Фоминых)
Cистемы автоматической сборки проектов (Полина Фоминых)
 
Масштабируемая архитектура фронтенда
Масштабируемая архитектура фронтендаМасштабируемая архитектура фронтенда
Масштабируемая архитектура фронтенда
 
Let's Talk About Junit 5
Let's Talk About Junit 5Let's Talk About Junit 5
Let's Talk About Junit 5
 
"Electron. How the most modern framework works" Oleksii Holubiev
"Electron. How the most modern framework works" Oleksii Holubiev"Electron. How the most modern framework works" Oleksii Holubiev
"Electron. How the most modern framework works" Oleksii Holubiev
 
Maven как средство сборки проекта
Maven как средство сборки проектаMaven как средство сборки проекта
Maven как средство сборки проекта
 
Vagrant: инструмент для разработки и тестирования (Odessa WebCamp 2015)
Vagrant: инструмент для разработки и тестирования (Odessa WebCamp 2015)Vagrant: инструмент для разработки и тестирования (Odessa WebCamp 2015)
Vagrant: инструмент для разработки и тестирования (Odessa WebCamp 2015)
 
Continuous Delivery для ASP.NET MVC проекта под Linux
Continuous Delivery для ASP.NET MVC проекта под LinuxContinuous Delivery для ASP.NET MVC проекта под Linux
Continuous Delivery для ASP.NET MVC проекта под Linux
 
Как это будет: ASP.NET Core
Как это будет: ASP.NET CoreКак это будет: ASP.NET Core
Как это будет: ASP.NET Core
 
Илья Евлампиев - Нагрузочное тестирование веб-приложений с помощью The Grinder
Илья Евлампиев - Нагрузочное тестирование веб-приложений с помощью The GrinderИлья Евлампиев - Нагрузочное тестирование веб-приложений с помощью The Grinder
Илья Евлампиев - Нагрузочное тестирование веб-приложений с помощью The Grinder
 
Software engineering seminars: gradle
 Software engineering seminars: gradle Software engineering seminars: gradle
Software engineering seminars: gradle
 
Mambility. Cтрах и ненависть к фрагментам
Mambility. Cтрах и ненависть к фрагментамMambility. Cтрах и ненависть к фрагментам
Mambility. Cтрах и ненависть к фрагментам
 

Viewers also liked

Viewers also liked (7)

Luonnostaan vahva klubin tuotekatalogi
Luonnostaan vahva klubin tuotekatalogi Luonnostaan vahva klubin tuotekatalogi
Luonnostaan vahva klubin tuotekatalogi
 
Продвижение компании
Продвижение компанииПродвижение компании
Продвижение компании
 
Продвижение фармацевтических продуктов
Продвижение фармацевтических продуктовПродвижение фармацевтических продуктов
Продвижение фармацевтических продуктов
 
Mobile marketing from analysis to launching a project
Mobile marketing from analysis to launching a projectMobile marketing from analysis to launching a project
Mobile marketing from analysis to launching a project
 
UX/UI design for web and mobile
UX/UI design for web and mobileUX/UI design for web and mobile
UX/UI design for web and mobile
 
Social projects and mobile apps to help them
Social projects and mobile apps to help themSocial projects and mobile apps to help them
Social projects and mobile apps to help them
 
Мобильные приложения без котиков
Мобильные приложения без котиковМобильные приложения без котиков
Мобильные приложения без котиков
 

Similar to Навигация в Android без боли и слез

Mobile automation uamobile
Mobile automation uamobileMobile automation uamobile
Mobile automation uamobile
UA Mobile
 

Similar to Навигация в Android без боли и слез (20)

Чистая архитектура, Артур Бадретдинов АБЦТ
Чистая архитектура, Артур Бадретдинов АБЦТЧистая архитектура, Артур Бадретдинов АБЦТ
Чистая архитектура, Артур Бадретдинов АБЦТ
 
Асинхронность и сопрограммы
Асинхронность и сопрограммыАсинхронность и сопрограммы
Асинхронность и сопрограммы
 
Практическое применение WebWorkers / Алексей Фомкин (Data Monsters)
Практическое применение WebWorkers / Алексей Фомкин (Data Monsters)Практическое применение WebWorkers / Алексей Фомкин (Data Monsters)
Практическое применение WebWorkers / Алексей Фомкин (Data Monsters)
 
Алексей Фомкин, Практическое применение Web Workers
Алексей Фомкин, Практическое применение Web WorkersАлексей Фомкин, Практическое применение Web Workers
Алексей Фомкин, Практическое применение Web Workers
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладка
 
Froglogic Squish
Froglogic Squish Froglogic Squish
Froglogic Squish
 
Как hh.ru дошли до 500 релизов в квартал без потери в качестве
Как hh.ru дошли до 500 релизов в квартал без потери в качествеКак hh.ru дошли до 500 релизов в квартал без потери в качестве
Как hh.ru дошли до 500 релизов в квартал без потери в качестве
 
Как построить свой фреймворк для автотестов?
Как построить свой фреймворк для автотестов?Как построить свой фреймворк для автотестов?
Как построить свой фреймворк для автотестов?
 
Load Testing
Load TestingLoad Testing
Load Testing
 
Реализация тестового фреймворка на основе OPEN-SOURCE инструментов
Реализация тестового фреймворка на основе OPEN-SOURCE инструментовРеализация тестового фреймворка на основе OPEN-SOURCE инструментов
Реализация тестового фреймворка на основе OPEN-SOURCE инструментов
 
Open Source Testing Framework: real project example and best practices
Open Source Testing Framework: real project example and best practicesOpen Source Testing Framework: real project example and best practices
Open Source Testing Framework: real project example and best practices
 
Подводная часть айсберга: что делать, чтобы автотесты не превратились в Титаник
Подводная часть айсберга: что делать, чтобы автотесты не превратились в ТитаникПодводная часть айсберга: что делать, чтобы автотесты не превратились в Титаник
Подводная часть айсберга: что делать, чтобы автотесты не превратились в Титаник
 
ВВЕДЕНИЕ В NODE.JS
ВВЕДЕНИЕ В NODE.JS ВВЕДЕНИЕ В NODE.JS
ВВЕДЕНИЕ В NODE.JS
 
Robot Framework: универсальный инструмент автоматизатора
Robot Framework: универсальный инструмент автоматизатораRobot Framework: универсальный инструмент автоматизатора
Robot Framework: универсальный инструмент автоматизатора
 
iOS and Android Mobile Test Automation
iOS and Android Mobile Test AutomationiOS and Android Mobile Test Automation
iOS and Android Mobile Test Automation
 
MockServer-driven development
MockServer-driven developmentMockServer-driven development
MockServer-driven development
 
Vagrant: tool for development and testing
Vagrant: tool for development and testingVagrant: tool for development and testing
Vagrant: tool for development and testing
 
Zero Downtime PHP Deployment with Envoyer And Forge
Zero Downtime PHP Deployment with Envoyer And ForgeZero Downtime PHP Deployment with Envoyer And Forge
Zero Downtime PHP Deployment with Envoyer And Forge
 
Mobile automation uamobile
Mobile automation uamobileMobile automation uamobile
Mobile automation uamobile
 
Moxy – реализация MVP под Android. С щепоткой магии
Moxy – реализация MVP под Android. С щепоткой магииMoxy – реализация MVP под Android. С щепоткой магии
Moxy – реализация MVP под Android. С щепоткой магии
 

Навигация в Android без боли и слез

  • 1. Навигация без боли и слез Константин Цховребов Android Team Leader
  • 2.
  • 4. В теории все прекрасно! Первый большой проект на MVP
  • 5. В теории все прекрасно! Первый большой проект на MVP На практике встречаешь ANDROID
  • 7. Навигация в андроид приложении ●  Переход между экранами
  • 8. Навигация в андроид приложении ●  Переход между экранами ●  Экраны сменяются в некотором контейнере
  • 9. Навигация в андроид приложении ●  Переход между экранами ●  Экраны сменяются в некотором контейнере ●  Для совершения перехода нужен Context
  • 10. А что если Fragment сделать презентером?
  • 11. А что если Fragment сделать презентером? 1.  Lifecycle
  • 12. А что если Fragment сделать презентером? 1.  Lifecycle 2.  Нужен универсальный подход (Activity/Fragment/View)
  • 13. А что если Fragment сделать презентером? 1.  Lifecycle 2.  Нужен универсальный подход (Activity/Fragment/View) 3.  Context (и другие классы)
  • 14. Mosby (http://hannesdorfmann.com/mosby/) public interface LoginView extends MvpView { public void showLoginForm(); public void showError(); public void showLoading(); public void loginSuccessful(); } public class LoginFragment … implements LoginView { … // Called when login was successful @Override public void loginSuccessful() { getActivity().finish(); } … }
  • 17. Требования к идеальной навигации ●  прямой доступ из презентера
  • 18. Требования к идеальной навигации ●  прямой доступ из презентера ●  не завязана на фрагменты
  • 19. Требования к идеальной навигации ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк
  • 20. Требования к идеальной навигации ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы
  • 21. Требования к идеальной навигации ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении
  • 22. Требования к идеальной навигации ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении ●  приспособлена для тестов
  • 23. Требования к идеальной навигации ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении ●  приспособлена для тестов ●  не зависит от жизненного цикла!
  • 24. //TODO: ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении ●  приспособлена для тестов ●  не зависит от жизненного цикла!
  • 29. Команды переходов Forward(String screenKey, Object transitionData); Back(); BackTo(String screenKey);
  • 30. Команды переходов Forward(String screenKey, Object transitionData); Back(); BackTo(String screenKey); Replace(String screenKey, Object transitionData);
  • 32. Navigator public interface Navigator { void applyCommand(Command command); }
  • 33. Navigator public interface Navigator { void applyCommand(Command command); } public class MainActivity extends Activity { private Navigator navigator = new Navigator() { @Override public void applyCommand(Command command) { ... } } }
  • 34. //TODO: ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении ●  приспособлена для тестов ●  не зависит от жизненного цикла!
  • 35. //TODO: ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении ●  приспособлена для тестов ●  не зависит от жизненного цикла! ✓
  • 36. public class Presenter { @Inject Navigator navigator; private void next() { navigator.applyCommand(new Forward(“Some screen”)); } }
  • 37. //TODO: ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении ●  приспособлена для тестов ●  не зависит от жизненного цикла! ✓
  • 38. //TODO: ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении ●  приспособлена для тестов ●  не зависит от жизненного цикла! ✓ ✓
  • 39.
  • 40.
  • 41. public class Presenter { @Inject Navigator navigator; private void authError() { navigator.applyCommand(new BackTo(null)); navigator.applyCommand(new Replace("Login screen", null)); navigator.applyCommand(new SystemMessage("Token expired!")); } }
  • 42. Router public class Router extends BaseRouter { void newRootScreenWithMessage(String screenKey, Object data, String message) {...} }
  • 43. Router public class Router extends BaseRouter { void newRootScreenWithMessage(String screenKey, Object data, String message) {...} } public class Presenter { @Inject Router router; private void authError() { router.newRootScreenWithMessage("Login screen", null, "Token expired!"); } }
  • 44. //TODO: ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении ●  приспособлена для тестов ●  не зависит от жизненного цикла! ✓ ✓
  • 45. //TODO: ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении ●  приспособлена для тестов ●  не зависит от жизненного цикла! ✓ ✓ ✓
  • 46. public class Router extends BaseRouter { private Navigator navigator; public void setNavigator(Navigator navigator) { this.navigator = navigator; } public void removeNavigator() { this.navigator = null; } public void newRootScreenWithMessage(String screenKey, Object data, String message) { if (navigator != null) { navigator.applyCommand(new BackTo(null)); navigator.applyCommand(new Replace("Login screen", null)); navigator.applyCommand(new SystemMessage("Token expired!")); } } }
  • 47. public class MainActivity extends Activity { @Override protected void onResume() { super.onResume(); router.setNavigator(navigator); } @Override protected void onPause() { super.onPause(); router.removeNavigator(); } }
  • 55. //TODO: ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении ●  приспособлена для тестов ●  не зависит от жизненного цикла! ✓ ✓ ✓
  • 56. //TODO: ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении ●  приспособлена для тестов ●  не зависит от жизненного цикла! ✓ ✓ ✓ ✓
  • 57. Unit тестирование @Test public void someTest() throws Exception { Router mockRouter = mock(Router.class); Presenter presenter = new Presenter(); presenter.onNextButtonClicked(); verify(mockRouter, times(1)).navigateTo( eq("Some screen"), argument.capture() ); }
  • 58. //TODO: ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении ●  приспособлена для тестов ●  не зависит от жизненного цикла! ✓ ✓ ✓ ✓
  • 59. //TODO: ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении ●  приспособлена для тестов ●  не зависит от жизненного цикла! ✓ ✓ ✓ ✓ ✓
  • 60. Расширение возможностей ●  в большинстве случаев достаточно добавить метод в Router и реализовать его с помощью Command ●  реже необходимо создать новую Command
  • 61. //TODO: ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении ●  приспособлена для тестов ●  не зависит от жизненного цикла! ✓ ✓ ✓ ✓ ✓
  • 62. //TODO: ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении ●  приспособлена для тестов ●  не зависит от жизненного цикла! ✓ ✓ ✓ ✓ ✓ ✓
  • 63. //TODO: ●  прямой доступ из презентера ●  не завязана на фрагменты ●  не фреймворк ●  короткие вызовы ●  легка в расширении ●  приспособлена для тестов ●  не зависит от жизненного цикла! ✓ ✓ ✓ ✓ ✓ ✓ ✓
  • 64. Cicerone Чичероне - (устар.) гид для иностранцев https://github.com/terrakok/Cicerone repositories { maven { url 'https://dl.bintray.com/terrakok/terramaven/' } } dependencies { //Cicerone compile 'ru.terrakok.cicerone:cicerone:1.0' }
  • 65.
  • 66. Для кого мы ее создали?
  • 67. Для кого мы ее создали? Для себя :)
  • 68. Для кого мы ее создали? Почему она может пригодиться вам? Для себя :)
  • 69. Для кого мы ее создали? ●  В приложении нелинейная навигация Почему она может пригодиться вам? Для себя :)
  • 70. Для кого мы ее создали? ●  В приложении нелинейная навигация ●  Отделение логики от отображения Почему она может пригодиться вам? Для себя :)
  • 71. Для кого мы ее создали? ●  В приложении нелинейная навигация ●  Отделение логики от отображения ●  Сохранение вызовов навигации после возвращения к приложению Почему она может пригодиться вам? Для себя :)
  • 72. Возможности Cicerone public class Router extends BaseRouter { void navigateTo(String screenKey, Object data); void newScreenChain(String screenKey, Object data); void newRootScreen(String screenKey, Object data); void replaceScreen(String screenKey, Object data); void backTo(String screenKey); void exit(); void exitWithMessage(String message); void showSystemMessage(String message); } public abstract class FragmentNavigator implements Navigator {}
  • 73. Спасибо за внимание! Вопросы? email: terrakok@mobileup.ru telegram: @terrakok https://github.com/terrakok/Cicerone