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
240
DC SF - Hitchhiking Through Jetpack Compose
jossiwolf
2
360
[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
180
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
370
From Java to Kotlin Multiplatform - DevFest Nuremberg
jossiwolf
0
120
Other Decks in Programming
See All in Programming
Vue・React マルチプロダクト開発を支える Vite
andpad
0
110
テストカバレッジ100%を10年続けて得られた学びと品質
mottyzzz
2
360
物語を動かす行動"量" #エンジニアニメ
konifar
14
5.7k
UbieのAIパートナーを支えるコンテキストエンジニアリング実践
syucream
2
790
オープンセミナー2025@広島「君はどこで動かすか?」アンケート結果
satoshi256kbyte
0
220
ライブ配信サービスの インフラのジレンマ -マルチクラウドに至ったワケ-
mirrativ
2
270
AIを活用し、今後に備えるための技術知識 / Basic Knowledge to Utilize AI
kishida
7
1.5k
LLMOpsのパフォーマンスを支える技術と現場で実践した改善
po3rin
8
1k
開発チーム・開発組織の設計改善スキルの向上
masuda220
PRO
17
9.5k
🔨 小さなビルドシステムを作る
momeemt
2
630
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
270
AIコーディングAgentとの向き合い方
eycjur
0
250
Featured
See All Featured
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.5k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
18
1.1k
Unsuck your backbone
ammeep
671
58k
Java REST API Framework Comparison - PWX 2021
mraible
33
8.8k
Automating Front-end Workflow
addyosmani
1370
200k
Fireside Chat
paigeccino
39
3.6k
YesSQL, Process and Tooling at Scale
rocio
173
14k
Speed Design
sergeychernyshev
32
1.1k
GraphQLとの向き合い方2022年版
quramy
49
14k
Writing Fast Ruby
sferik
628
62k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
34
6k
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; }