AndThen executes before completable finished

坚强是说给别人听的谎言 提交于 2019-12-04 04:55:10

问题


Let's take two methods written with Rx:

Maybe<Foo> getFooFromLocal
Single<Foo> getFooFromNetwork

I want to write a chain when we check our local storage for Foo. If we don't have any Foo we should get it from the network then save it to the local storage and again get it from local storage and pass it to our subscriber.

storage
            .getFooFromLocal()
            .switchIfEmpty(network.getFooFromNetwork().map { it[0] }
                    .flatMapCompletable { storage.saveFoo(it) }
                    .andThen(storage.getFooFromLocal()))
                    .subscriber(/**/)

The problem is that andThen part completes before completable passed into flatMapCompletable. I found out that I can get rid of this problem if I wrap into Maybe.defer{}. But according to the documentation of andThen it

Returns a Maybe which will subscribe to this Completable.

And maybe is already

Represents a deferred computation and emission of a maybe value or exception

So the question is why my andThen part run before completable finished. And what is the best and elegant way to write such chains.

Calls log :

06:05:58.803 getFooFromLocal
06:05:58.804 getFooFromLocal
06:05:58.804 getFooFromNetwork
06:05:59.963 saveFoo

回答1:


This works for me:

public class AndThenTest {

    Integer value;

    @Test
    public void test() {
        getFromLocal()
        .switchIfEmpty(getFromNetwork()
                .flatMapCompletable(v -> saveFoo(v))
                .andThen(getFromLocal()))
        .doOnSuccess(e -> System.out.println("Success: " + e))
        .test()
        .awaitDone(5, TimeUnit.SECONDS)
        .assertResult(10);
    }

    Maybe<Integer> getFromLocal() {
        return Maybe.fromCallable(() -> {
            System.out.println("FromLocal called");
            return value;
        });
    }

    Single<Integer> getFromNetwork() {
        return Single.fromCallable(() -> {
            System.out.println("FromNetwork called");
            return 10;
        }).delay(100, TimeUnit.MILLISECONDS)
                ;
    }

    Completable saveFoo(Integer v) {
        return Completable.fromRunnable(() -> {
            System.out.println("SaveFoo called");
            value = v;
        });
    }
}

and prints:

FromLocal called
FromNetwork called
SaveFoo called
FromLocal called
Success: 10

So my guess is that there is a mistake in one of the methods you are not showing.



来源:https://stackoverflow.com/questions/45834989/andthen-executes-before-completable-finished

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!