Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chaining requests in Retrofit + RxJava

Tags:

I have 2 APIs that I want to make request to in sequence and store their data in SQLite.

First I want to make request to API A and store its data in SQL table a. Then make request to API B and store its data in table b and some data in table a_b. The data stored in a_b is from request B alone.

How can I do this using RxJava. I read somewhere about using flatMap for this, something like this

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;
        });
    });

If I wasn't using lambda functions, this would look as ugly as normal nested calls. Is this a better way to do it?

like image 844
Sourabh Avatar asked Apr 22 '16 04:04

Sourabh


People also ask

How does RxJava chain work?

It changes the thread as many times as you write it. flatMap starts the chain only during root chain data emission. No actions are performed during the root stream subscription process. Operators interval/delay/timer subscribe to computation under the hood, by default.

How do you use RxJava with retrofit?

To use RxJava in retrofit environment we need to do just two major changes: Add the RxJava in Retrofit Builder. Use Observable type in the interface instead of Call.

What is retrofit RxJava?

Retrofit is a HTTP Client for Android and Java developed by Square. We are going to integrate Retrofit with RxJava to simplify threading in our app. In addition, we will also integrate RxAndroid to make network calls.

What is API in Retrofit?

Retrofit is a type-safe REST client for Android, Java and Kotlin developed by Square. The library provides a powerful framework for authenticating and interacting with APIs and sending network requests with OkHttp.


2 Answers

I don't think using map operator is the best way to go with things like storing the result of the api call.

What I like to do is to separate those things inside doOnNext operators. So your example would be something like this:

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

(add necessary observeOn and subscribeOn yourself, exactly like you need them)

like image 122
Bartek Lipinski Avatar answered Oct 05 '22 04:10

Bartek Lipinski


Yes, you can use flatmap for this exact purpose. See the below example (Assuming your service A returns Observable<FooA> and service B returns 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               }         }); 
like image 23
Much Overflow Avatar answered Oct 05 '22 03:10

Much Overflow