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
130
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
180
DC SF - Hitchhiking Through Jetpack Compose
jossiwolf
2
290
[DC SF 2022] Hitchhiking through Jetpack Compose
jossiwolf
2
310
[Berlin 2021] Hitchhiker's Guide to Compose
jossiwolf
4
550
From LiveData to Coroutines & Flow - DevFest ZA
jossiwolf
2
140
From LiveData to Coroutines & Flow - Android Summit
jossiwolf
2
130
From LiveData to Coroutines & Flow
jossiwolf
1
650
Experimenting with the Kotlin Compiler
jossiwolf
0
210
From Java to Kotlin Multiplatform - DevFest Nuremberg
jossiwolf
0
79
Other Decks in Programming
See All in Programming
Native Federation: The Future of Micro Frontends in Angular
manfredsteyer
PRO
0
170
Jetpack Composeとデザインシステム
rmakiyama
0
230
JavaScript Closure
asoluka
0
2k
slow types ってなんだろう?
karad
0
210
TypeScriptでもLLMアプリケーション開発 / LLM Application In Typescript
rkaga
5
1.3k
GNU Makeの使い方 / How to use GNU Make
kaityo256
PRO
13
4.3k
How to improve maintainability and readability of your automated tests? ( #scrumniigata )
teyamagu
PRO
1
130
Documentation testsの恩恵 / Documentation testing benefits
ssssota
1
560
『WordPressコミュニティで学ぶ』OSS貢献の多様性
ippey
0
230
Next.js App Router
quramy
14
2.3k
Runtime Objects in Rust
mitsuhiko
0
220
Balkan Ruby 2024 — How and why to run SQLite on Rails in production
fractaledmind
0
110
Featured
See All Featured
Learning to Love Humans: Emotional Interface Design
aarron
267
39k
Designing on Purpose - Digital PM Summit 2013
jponch
111
6.5k
Optimising Largest Contentful Paint
csswizardry
13
2.4k
Docker and Python
trallard
35
2.7k
GraphQLとの向き合い方2022年版
quramy
33
13k
VelocityConf: Rendering Performance Case Studies
addyosmani
321
23k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
23
1.7k
Making Projects Easy
brettharned
109
5.5k
A Philosophy of Restraint
colly
197
16k
The Illustrated Children's Guide to Kubernetes
chrisshort
32
47k
Designing with Data
zakiwarfel
96
4.8k
Statistics for Hackers
jakevdp
790
220k
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; }