Search code examples
androidrx-java2mosby

Losing Events during RxJava subscribeOn()


I got the following code using Mosby.

Fragment:

@Override
public Observable<CardInfo> loadCardIntent() {
    return Observable.just(new CardInfo(cardselected, PreferenceManager.getDefaultSharedPreferences(getContext())
            .getBoolean(PreferencesVariables.SHOW_BACK_CARD.toString(), false)))
            //.delay(500, TimeUnit.MILLISECONDS)
            .doOnNext(showBack -> Log.d(TAG, "Show card back: " + showBack));
 }

@Override
 public Observable<CardInfo> loadFrontIntent() {
        return RxView.clicks(cardBackImageView)
                .map(showFront -> new CardInfo(cardselected, false))
                .doOnNext(showFront -> Log.d(TAG, "Show card front"));
}

@Override
public Observable<Boolean> hideCardIntent() {
        return clicks(cardFrontImageView)
                .map(ignored -> true)
                .doOnNext(close -> Log.d(TAG, "Close card activity"));
}

Presenter:

@Override
    protected void bindIntents() {

        Observable<CardViewState> showSelectedCard = intent(CardView::loadCardIntent)
                .switchMap(cardInfo -> interactor.getCard(cardInfo))
                .doOnError(error -> System.out.print(error.getMessage()));

        Observable<CardViewState> showFront = intent(CardView::loadFrontIntent)
                .switchMap(cardInfo -> interactor.getCard(cardInfo))
                .doOnError(error -> System.out.print(error.getMessage()));

        Observable<CardViewState> hideCard = intent(CardView::hideCardIntent)
                .switchMap(ignored -> interactor.hideCard());

        Observable<CardViewState> intents = Observable.merge(showSelectedCard, showFront, hideCard)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());

        subscribeViewState(intents, CardView::render);
    }

Fragment:

@Override
public void render(CardViewState viewState) {
    if (viewState instanceof CardViewState.CardBackState) {
        renderCard(R.raw.planningpoker_rueckseite, cardBackImageView);
        renderCard(((CardViewState.CardBackState) viewState).card, cardFrontImageView);
        showCardBack();
    } else if (viewState instanceof CardViewState.CardFrontState) {
        renderCard(R.raw.planningpoker_rueckseite, cardBackImageView);
        renderCard(((CardViewState.CardFrontState) viewState).card, cardFrontImageView);
        showCardFront();
    } else if (viewState instanceof CardViewState.CardCloseState) {
        getActivity().finish();
    }
}

Interactor:

Observable<CardViewState> getCard(CardInfo cardInfo) {
    return cardInfo.showBack ? Observable.just(new CardViewState.CardBackState(CARDS[cardInfo.card])) :
            Observable.just(new CardViewState.CardFrontState(CARDS[cardInfo.card]));
}

Observable<CardViewState> hideCard() {
    return Observable.just(new CardViewState.CardCloseState());
}

Without the delay in loadCardIntent() the render()-method does not get triggered with the CardBackState. But I don't want to use a arbitrary delay to ensure the right methods get triggered. Is there any other way to ensure that all events get emitted?

Thanks for the help.


Solution

  • My solution for now is to use Schedulers.trampoline(). It is not ideal and in no way sufficient but it allows me to get rid of the delay that is more of a hassle.

    The problem that Schedulers.trampoline() seem to be solving is that the change onto another thread takes a short amount of time. And that causes the event to get lost. So staying on the same thread fixes this.