Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Model View Intent - An Introduction
Search
Jossi Wolf
August 16, 2017
Programming
0
150
Model View Intent - An Introduction
Jossi Wolf
August 16, 2017
Tweet
Share
More Decks by Jossi Wolf
See All by Jossi Wolf
Understanding Recomposition Performance Pitfalls
jossiwolf
3
230
DC SF - Hitchhiking Through Jetpack Compose
jossiwolf
2
350
[DC SF 2022] Hitchhiking through Jetpack Compose
jossiwolf
2
390
[Berlin 2021] Hitchhiker's Guide to Compose
jossiwolf
4
660
From LiveData to Coroutines & Flow - DevFest ZA
jossiwolf
2
170
From LiveData to Coroutines & Flow - Android Summit
jossiwolf
2
160
From LiveData to Coroutines & Flow
jossiwolf
1
690
Experimenting with the Kotlin Compiler
jossiwolf
0
360
From Java to Kotlin Multiplatform - DevFest Nuremberg
jossiwolf
0
120
Other Decks in Programming
See All in Programming
Hack Claude Code with Claude Code
choplin
5
2.3k
NPOでのDevinの活用
codeforeveryone
0
860
iOS 26にアップデートすると実機でのHot Reloadができない?
umigishiaoi
0
130
AIプログラマーDevinは PHPerの夢を見るか?
shinyasaita
1
230
システム成長を止めない!本番無停止テーブル移行の全貌
sakawe_ee
1
210
Modern Angular with Signals and Signal Store:New Rules for Your Architecture @enterJS Advanced Angular Day 2025
manfredsteyer
PRO
0
230
Team operations that are not burdened by SRE
kazatohiei
1
320
猫と暮らす Google Nest Cam生活🐈 / WebRTC with Google Nest Cam
yutailang0119
0
160
Quand Symfony, ApiPlatform, OpenAI et LangChain s'allient pour exploiter vos PDF : de la théorie à la production…
ahmedbhs123
0
210
ソフトウェア品質を数字で捉える技術。事業成長を支えるシステム品質の マネジメント
takuya542
2
14k
ペアプロ × 生成AI 現場での実践と課題について / generative-ai-in-pair-programming
codmoninc
2
19k
#QiitaBash MCPのセキュリティ
ryosukedtomita
1
1.4k
Featured
See All Featured
Gamification - CAS2011
davidbonilla
81
5.4k
GitHub's CSS Performance
jonrohan
1031
460k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
251
21k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Music & Morning Musume
bryan
46
6.6k
Building a Scalable Design System with Sketch
lauravandoore
462
33k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
181
54k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
126
53k
Product Roadmaps are Hard
iamctodd
PRO
54
11k
Bash Introduction
62gerente
613
210k
Become a Pro
speakerdeck
PRO
29
5.4k
Why Our Code Smells
bkeepers
PRO
336
57k
Transcript
Model View Intent An Introduction
Jossi Wolf Android Developer About Me
MVI MVP MVC MVVM Redux Flux God-like Activities
Model View Intent
None
A B C data data Unidirectional Data Flow D data
data
A B C data data Unidirectional Data Flow D data
data
someModel.set(…) Immutability
someModel.set(…) Immutability
String calendar = "calendar"; System.out.println(calendar.toUpperCase()); // CALENDAR Pure Functions
public class SchoolsViewState { boolean loading; Throwable error; List<SchoolsModel> schools;
} State Model
Data Flow in MVI View Intents (User Actions) Business Logic
emits Presenter Model
public interface SchoolsViewPresenterContract { interface SchoolsViewActions { } interface SchoolsPresenterActions
{ } }
interface SchoolsPresenterActions { void loadSchools(); }
interface SchoolsViewActions { void showLoading(); void showSuccess(); void showError(); }
interface SchoolsViewActions { void render(SchoolsViewState state); }
public class SchoolsActivity implements SchoolsViewActions { @Override public void render(SchoolsViewState
state) { // The view decides how to render the state } }
@Override public void render(SchoolsViewState state) { if (state.getError() != null)
{ showError(state.getError().getMessage()); } if (state.isLoading()) { showLoader(); clearAdapter(); } else if (!state.isLoading()) { hideLoader(); } if (state.getSchools() != null) { showSchools(state.getSchools()); } }
public class ExampleStateModel { private boolean loading; private Throwable error;
private List<SchoolsModel> data; ExampleStateModel(boolean loading, Throwable error, List<SchoolsModel> data) { // set everything } }
public class ExampleStateModel { private boolean loading; private Throwable error;
private List<SchoolsModel> data; private ExampleStateModel( boolean loading, Throwable error, List<SchoolsModel> data) { // set everything } }
public static SchoolsViewState LoadingState() { return new SchoolsViewState(true, null, null);
} public static SchoolsViewState ErrorState(Throwable error) { return new SchoolsViewState(false, error, null); } public static SchoolsViewState DataLoadedState(List<SchoolsModel> schools) { return new SchoolsViewState(false, null, schools); }
State Reducer
HomeViewState { loading = false error = null data =
[…] }
HomeViewState { loading = false error = null data =
[a, b, c] } HomeViewState { loading = false error = null data = [x, y, z] } [a, b, c, x, y, z]
@Test public void loadSchoolsSuccessful() { when(api.getHamburgSchools()) .thenReturn(Observable.just(generateFakeList())); schoolsPresenter.loadSchools(); verify(schoolsView).render(SchoolsViewState.LoadingState()); verify(schoolsView).render(SchoolsViewState.DataLoadedState(generateFakeList()));
}
@Test public void loadSchoolsNotSuccessful() { Throwable throwable = new Throwable();
when(api.getHamburgSchools()) .thenReturn(Observable.error(throwable)); schoolsPresenter.loadSchools(); verify(schoolsView).render(SchoolsViewState.LoadingState()); verify(schoolsView).render(SchoolsViewState.ErrorState(throwable)); }
Predictability = = + ?
Predictability = = =
Predictability LoadingState DataLoadedState ErrorState
Readable Code Presenter View Interactor Database Network void a( )
void b( )
None
Reading on https://github.com/jossiwolf/MVI-Example https://www.youtube.com/watch?v=0IKHxjkgop4 http://hannesdorfmann.com/android/mosby3-mvi-1 https://github.com/oldergod/android-architecture
public MainViewState reduce(MainViewState previous, MainViewState next) { MainViewState computedViewState =
MainViewState.Companion.ErrorState(new Throwable("No State")); if (next.getLoading()) { computedViewState = MainViewState.Companion.LoadingState(); } else if (next.getError() != null) { computedViewState = MainViewState.Companion.ErrorState(next.getError()); } else if (next.getData() != null) { List<String> data = new ArrayList<>(); if (previous.getData() != null) { data.addAll(previous.getData()); } data.addAll(next.getData()); computedViewState = MainViewState.Companion.DataLoadedState(data); } return computedViewState; }