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
310
DC SF - Hitchhiking Through Jetpack Compose
jossiwolf
2
430
[DC SF 2022] Hitchhiking through Jetpack Compose
jossiwolf
2
450
[Berlin 2021] Hitchhiker's Guide to Compose
jossiwolf
4
710
From LiveData to Coroutines & Flow - DevFest ZA
jossiwolf
2
230
From LiveData to Coroutines & Flow - Android Summit
jossiwolf
2
210
From LiveData to Coroutines & Flow
jossiwolf
1
740
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
490
Java 27新機能 / Java 27 new features
kishida
2
200
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
1
630
Streamlitで実現する自然言語データアプリ開発
ayumu_yamaguchi
1
340
設計次第でAIコードの読む量は減らせる / designing-for-code-reading
minodriven
34
16k
複雑なUIコンポーネントとの ⻑い付き合い⽅:波及するバグからテスト戦略を経て、安全な再設計へ
mixplace
0
110
Jetpack Compose Mechanisms
skydoves
2
550
GitHubハンズオン講座 — 実務レベルのチーム開発のフローを身につけよう
junhat6
0
120
Are APIs Still Relevant in the AI Era?
soyuka
0
430
iOS 27でニュースアプリはどう変わる!? 〜日経電子版の新機能対応と、開発事例から〜
lynnswap
7
13k
mrbgem 三角測量 開発
ogom
0
210
dotNET_vulnclicker_intro.pdf
deka_morita
0
110
Featured
See All Featured
KATA
mclloyd
PRO
35
16k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.6k
Into the Great Unknown - MozCon
thekraken
41
2.8k
Test your architecture with Archunit
thirion
2
2.4k
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
1
620
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
440
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
570
Producing Creativity
orderedlist
PRO
348
41k
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
540
Being A Developer After 40
akosma
92
590k
Leo the Paperboy
mayatellez
10
2.4k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
4
4.3k
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; }