RxJava Retrofit chain of requests with foreach loop

Viewed 2352

I'm trying to migrate from using plain Retrofit to using the RxJava extension for retrofit in order to make chain of API calls on the background thread.

For example, I have an object called ModelGroup which has a list of ModelPerson objects. My goal is to do the following.

  1. Send ModelGroup to the server and receive a response, which is an integer, representing the newly inserted ID, let's call it newGroupId.
  2. For each ModelPerson in ModelGroup, set Person.groupId to newGroupId.
  3. Send each person to the server.
  4. If all ModelPerson objects from the ModelGroup were successfully updated with newGroupId then respond with onSuccess, otherwise onError.

My current solution can be seen below.

private void makeGroupInsert(ModelGroup modelGroup) {

    int newGroupId = myApi.insertNewGroup(modelGroup.getName(), modelGroup.getRating())
            .execute()
            .body();

    for (ModelPerson person : modelGroup.getPersons()) {
        person.setGroupId(newGroupId);

        String response = myApi.insertNewPerson(
                person.getGroup_id(),
                person.getFirst_Name(),
                person.getLast_Name())
                .execute()
                .body();

        if (!response.equals("success")) {
            // One failed to update, send error to main thread.
        }
    }

    // All succeeded, send success back to main thread.
}

Question

How can I achieve the same (or better) functionality using a RxJava + Retrofit solution?

EDIT 1

MyApi is defined below.

public interface MyApi {

    @POST("insert_new_group")
    Call<Integer> insertNewGroup(@Query("group_name") String groupName,
                                   @Query("group_rating") int rating);

    @POST("insert_new_person")
    Call<String> insertNewPerson(@Query("group_id") int groupId,
                                   @Query("first_name") String firstName,
                                   @Query("last_name") String lastName);
}
1 Answers

First of all, you need to change Retrofit beans to use Observables. For example, it can look like the following line:

@POST("insert_new_group")
Observable<Integer> insertNewGroup(...

Then you can chain requests:

void updateData() {
    myApi.insertNewGroup(modelGroup.getName(), modelGroup.getRating()) //Creating new group and getting its ID
            .switchMap(this::setGroupIdAll) //Calling observable that will loop thru all persons and set their groupIDs
            .subscribe(
                    (n) -> {/*you will get String after every 'insertNewPerson' run*/},
                    (e) -> {/*error handling*/}
            );

}

Observable<String> setGroupIdAll(Integer id) {
    return Observable.fromIterable(personsIterable) //personsIterable contains all your ModelPerson objects
            .flatMap(this::updatePerson); //Call Observabl;e that will send updated person to the server
}

Observable<String> updatePerson(ModelPerson person) {
    return myApi.insertNewPerson(
            person.getGroup_id(),
            person.getFirst_Name(),
            person.getLast_Name());
}
Related