Retrofit + RxJava 中的链接请求

Posted

技术标签:

【中文标题】Retrofit + RxJava 中的链接请求【英文标题】:Chaining requests in Retrofit + 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 函数,这看起来和普通的嵌套调用一样难看。这是更好的方法吗?

【问题讨论】:

【参考方案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 中做到这一点?

以上是关于Retrofit + RxJava 中的链接请求的主要内容,如果未能解决你的问题,请参考以下文章

Retrofit2.0+RxJava网络请求异常统一处理

Glide工具类/OkGo网络请求/MVP请求数据/Retrofit+RxJava/ARouter/补间动画/轮播图等等等等等 记录一下~~

Glide工具类/OkGo网络请求/MVP请求数据/Retrofit+RxJava/ARouter/补间动画/轮播图等等等等等 记录一下~~

Glide工具类/OkGo网络请求/MVP请求数据/Retrofit+RxJava/ARouter/补间动画/轮播图等等等等等 记录一下~~

RxJava + Retrofit完成网络请求

RxJava+Retrofit实现网络请求