【问题标题】:Chaining requests in Retrofit + RxJavaRetrofit + RxJava 中的链接请求
【发布时间】:2016-08-15 13:39:27
【问题描述】:

我有 2 个 API,我想按顺序发出请求并将它们的数据存储在 SQLite 中。

首先我想向 API A 发出请求并将其数据存储在 SQL 表 a 中。然后向 APIB 发出请求,并将其数据存储在表 b 中,并将一些数据存储在表 a_b 中。 a_b 中存储的数据仅来自请求 B

如何使用 RxJava 做到这一点。我在某处读到了关于为此使用 flatMap 的信息,类似这样的

apiService.A()
    // store in DB here? How? maybe use map()?
    .flatMap(modelA -> {
        // or maybe store modelA in DB here?
        return apiService.B().map(modelB -> {
            storeInDB()l // store B here ?
            return modelB;
        });
    });

如果我不使用 lambda 函数,这看起来和普通的嵌套调用一样难看。这是更好的方法吗?

【问题讨论】:

    标签: android rx-java retrofit2


    【解决方案1】:

    我不认为使用 map 运算符是处理诸如存储 api 调用结果之类的最佳方法。

    我喜欢做的是在 doOnNext 运算符中分离这些东西。所以你的例子是这样的:

    apiService.A()
            .doOnNext(modelA -> db.store(modelA))
            .flatMap(modelA -> apiService.B())
            .doOnNext(modelB -> db.store(modelB));
    

    (添加必要的 observeOnsubscribeOn 自己,就像你需要它们一样)

    【讨论】:

    • 我不知道 Rx 的 do 运营商。阅读其文档后,doOnComplete 不是更好的功能吗?
    • @Sourabh 这取决于您的Observable。如果在从 api 成功调用后调用 onComplete,则可以。如果您的Observable 可以发出多个事件,那么您应该选择doOnNext。在您的情况下(Retrofit)使用doOnNextdoOnComplete 将得到相同的结果,但实际上doOnComplete 可能更直观(我出于纯粹的习惯使用doOnNext)。
    • 我的意思是,使用doOnComplete 而不是flatMap
    • ...B() 不依赖于A() 的结果(SO 的 5 分钟评论编辑时间)
    • 使用doOnComplete 而不是flatMap 是错误的,因为doOnComplete 不会更改流中的Observable,而flatMap 会。换句话说,如果你使用flatMap,你可以只使用一个subscribe,而试图使用doOnComplete而不是这个会迫使你在这个apiService.B().subscribe(...)中调用apiService.B().subscribe(...)doOnComplete(这看起来很难看)
    【解决方案2】:

    是的,您可以将 flatmap 用于此目的。看下面的例子(假设你的服务A返回Observable<FooA>,服务B返回Observable<FooB>

    api.serviceA()
            .flatMap(new Func1<FooA, Observable<FooB>>() {
                @Override
                public Observable<FooB> call(FooA fooA) {
                    // code to save data from service A to db
    
                    // call service B
                    return api.serviceB();
                }
             })
             .subscribeOn(Schedulers.io())
             .observeOn(AndroidSchedulers.mainThread())
             .subscribe(new Subscriber<FooB>() {
                 @Override
                 public void onCompleted() {
                 }
    
                 @Override
                 public void onError(Throwable e) {
    
                 }
    
                 @Override
                 public void onNext(FooB fooB) {
                     // code to save data from service B to db
    
                 }
            });
    

    【讨论】:

    • 如果我在 onNext 中编写代码将数据保存到数据库,它将在主线程上运行,对吗?如何在后台线程上将数据保存到数据库?
    • 加入另一个flatMap 运算符。 api.serviceA().flatMap((FooA) -&gt; {// call service B}).flatMap((FooB) -&gt; {// save data from service B and return a observable stating success / failure}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).doOnNext((isSuccess) -&gt; {// Only this will execute on main thread})
    • 你会如何在 RxJava2 中做到这一点?
    猜你喜欢
    • 1970-01-01
    • 2016-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-26
    • 1970-01-01
    • 1970-01-01
    • 2017-03-01
    相关资源
    最近更新 更多