Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Model View Intent - An Introduction
Search
Jossi Wolf
August 16, 2017
Programming
170
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Model View Intent - An Introduction
Jossi Wolf
August 16, 2017
More Decks by Jossi Wolf
See All by Jossi Wolf
Understanding Recomposition Performance Pitfalls
jossiwolf
3
320
DC SF - Hitchhiking Through Jetpack Compose
jossiwolf
2
430
[DC SF 2022] Hitchhiking through Jetpack Compose
jossiwolf
2
460
[Berlin 2021] Hitchhiker's Guide to Compose
jossiwolf
4
730
From LiveData to Coroutines & Flow - DevFest ZA
jossiwolf
2
230
From LiveData to Coroutines & Flow - Android Summit
jossiwolf
2
220
From LiveData to Coroutines & Flow
jossiwolf
1
750
Experimenting with the Kotlin Compiler
jossiwolf
0
530
From Java to Kotlin Multiplatform - DevFest Nuremberg
jossiwolf
0
170
Other Decks in Programming
See All in Programming
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
230
学びを記事・スライド・Xへ高速展開する― AI-assisted Learning Loopで回すコンテンツ生成術
ochtum
0
200
まずはコードより業務と向き合う:テーブル解体のためにPdMを呼んだ話
sakawe_ee
0
210
AI時代のFlutter品質設計 — アプリ品質を守るQuality Layers
omatty198
0
370
Railsバージョンを4倍にした話
optim
0
1k
AIがコードを書いてくれる時代、我々は何を確かめるのか
yosuke_furukawa
PRO
13
5.8k
PumaからFalconに移行したRailsアプリケーションでの実践
falcon8823
0
370
Будущее локальных LLM – Алексей Голобурдин, PythoNN
sobolevn
0
120
protojson における文字化けの扱い
kazuki1023
0
240
LLM 101: Exploring LLMs, Starting with Tokens.
dalinaum
0
100
Coding with AI: How to trust the storyteller (AWS Community Day Adria, Ljubljana 2026)
slobodan
0
140
作れるエンジニアから、価値を届けるエンジニアへ
ryunakayama
1
250
Featured
See All Featured
We Are The Robots
honzajavorek
0
440
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.9k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.4k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
2
390
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
580
Mobile First: as difficult as doing things right
swwweet
225
10k
The World Runs on Bad Software
bkeepers
PRO
72
12k
A Modern Web Designer's Workflow
chriscoyier
699
190k
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
Ten Tips & Tricks for a 🌱 transition
stuffmc
1
280
The Cost Of JavaScript in 2023
addyosmani
56
10k
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
760
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; }