Trying new architecture paradigm where presenter creates immutable state(model) stream and view just renders it.
Can't understand how to handle situations where we need to make some event for the one time only. There are couple examples.
1) Notes app. We have editText and saveButton. User clicks saveButton, some processing happens and editText should be cleared. Could you guys please describe what will be in our ViewState here and approximate logic flow?
Questions and pitfalls I see now:
- We subscribe to
editText.textChanges()in presenter. If we will havetextin ourViewStateand render it each render call then we will fall into recursion because it will emit new textChange and will update state and render again. - Do we need
textinViewStateto restore it on orientation text or process kill/restore, looks like it works out of box here. But imaginerecyclerViews scroll position. We definitely need to save it to restore. We can't restore it on each render call cause it looks weird, isn't it? - If we consider such logic as side effect and will call
.doOnNext{ view.clearText() }it makes sense, but do we have reference to view in canonical MVI implementation? Mosby doesn't have it as I see. - It makes sense but there is possibility of view being dead in the moment of
doOnNextcall. MVI should help us with this but only if it's the part ofViewState, right?
2) Github app. First screen(Org): orgEditText, okButton, progressBar. Second screen (Repos): recyclerView. When user enters organization into orgEditText and clicks okButton app should make request to API and on success navigate to Repos screen on success or show toast on failure. Again could you please describe ViewState for Org screen and what logic should look like?
Questions and pitfalls I see now:
- We should show
progressBarand disableokButtonwhile loading. We should have like loading/content/error sealed class(lets call itContentState) and have its instance in ourViewState. View knows how to renderContentState.loadingand showsprogressBarand disablesokButton. Am I right? - How to handle navigation then? The same questions as 1.3 and 1.4.
- I've seen opinions that navigation should be considered as side effect, but again 1.4.
- Toast - is there something in state or we consider this as side effect? Same problems.
Google suggests SingleLiveEvent solution, but it looks weird and then there should be as much LiveData<SingleLiveEvent> streams as we have such things, not really a single source of truth.
Others suggest new intent generated from render func which is better but there is a possibility that some async operations will change state again and we'll get second Toast while first is showing and so on.