sockeqwe / mosby

A Model-View-Presenter / Model-View-Intent library for modern Android apps
http://hannesdorfmann.com/mosby/
Apache License 2.0
5.49k stars 841 forks source link

MVI - Stop multi event emissions on state change #241

Closed MFlisar closed 7 years ago

MFlisar commented 7 years ago

I'm using an observable like following to update the UI if the selected view is changed (in my case I'm showing just different data of the same type, based on the selected view).

So what my presenter contains is following:

@Override
protected void bindIntents()
{
    ArrayList<Observable<FolderPartialStateChanges>> observables = new ArrayList<>();

            // ... other intents...

    observables.add(intent(view -> view.selectedViewIntent())
            .doOnNext(ignored -> L.withGroup(LOG_GROUP).d("Intent: VOLLE Ordner laden..."))
            .flatMap(viewState -> FolderInteractor.loadFoldersLoaded(viewState)
                    .map(folder -> (FolderPartialStateChanges)new FolderPartialStateChanges.SingleFolderLoaded(folder))
                    .startWith(new FolderPartialStateChanges.LoadingSingleFoldersStarted())
                    .concatWith(Observable.just(new FolderPartialStateChanges.LoadingSingleFoldersFinished()))
                    .onErrorReturn(FolderPartialStateChanges.LoadingSingleFoldersError::new)
                    .subscribeOn(Schedulers.io())
            )
    );

    Observable<FolderPartialStateChanges> allIntents = Observable.merge(observables);
    FolderViewState initialState = FolderViewState.builder().build();
    Observable<FolderViewState> stateObservable = allIntents.scan(initialState, this::viewStateReducer)
            .observeOn(AndroidSchedulers.mainThread());
    subscribeViewState(stateObservable, FolderControllerView::render);
}

The FolderInteractor.loadFoldersEmpty() is emitting a lot of items, one by one, that's why it's surrounded with a start and end state. That works all fine, but now I face a problem. If the user changes the view while the loadFoldersEmpty() is still emitting items, the reduce functing is mixing up states... Now my question is, I have hot observables only, how can I stop them from emitting when the view changes without unsubscribing? How would you solve the problem or do you have any other idea?

PS: I'm sorry for posting here, I tried to post this on your block twice, but both times disqus was marking my post as spam and I can't contact you there to tell you...

sockeqwe commented 7 years ago

Use switchMap() instead of flatMap() . switchMap unsubscribes any previous FolderInteractor.loadFoldersLoaded(viewState) observable before continuing.

MFlisar notifications@github.com schrieb am Fr., 28. Apr. 2017, 08:14:

I'm using an observable like following to update the UI if the selected view is changed (in my case I'm showing just different data of the same type, based on the selected view).

So what my presenter contains is following:

@Override protected void bindIntents() { ArrayList<Observable> observables = new ArrayList<>();

        // ... other intents...

observables.add(intent(view -> view.selectedViewIntent()) .doOnNext(ignored -> L.withGroup(LOG_GROUP).d("Intent: VOLLE Ordner laden...")) .flatMap(viewState -> FolderInteractor.loadFoldersLoaded(viewState) .map(folder -> (FolderPartialStateChanges)new FolderPartialStateChanges.SingleFolderLoaded(folder)) .startWith(new FolderPartialStateChanges.LoadingSingleFoldersStarted()) .concatWith(Observable.just(new FolderPartialStateChanges.LoadingSingleFoldersFinished())) .onErrorReturn(FolderPartialStateChanges.LoadingSingleFoldersError::new) .subscribeOn(Schedulers.io()) ) );

Observable allIntents = Observable.merge(observables); FolderViewState initialState = FolderViewState.builder().build(); Observable stateObservable = allIntents.scan(initialState, this::viewStateReducer) .observeOn(AndroidSchedulers.mainThread()); subscribeViewState(stateObservable, FolderControllerView::render); }

The FolderInteractor.loadFoldersEmpty() is emitting a lot of items, one by one, that's why it's surrounded with a start and end state. That works all fine, but now I face a problem. If the user changes the view while the loadFoldersEmpty() is still emitting items, the reduce functing is mixing up states... Now my question is, I have hot observables only, how can I stop them from emitting when the view changes without unsubscribing? How would you solve the problem or do you have any other idea?

PS: I'm sorry for posting here, I tried to post this on your block twice, but both times disqus was marking my post as spam and I can't contact you there to tell you...

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/sockeqwe/mosby/issues/241, or mute the thread https://github.com/notifications/unsubscribe-auth/AAjnrqYQ4Md2JLxMZIchiCIMeW76mDDZks5r0YOogaJpZM4NLF-b .