RxJava Retrofit 带有 foreach 循环的请求链

RxJava Retrofit chain of requests with foreach loop

我正在尝试从使用普通 Retrofit 迁移到使用 RxJava 扩展进行改造,以便在后台线程上进行 API 调用链。

例如,我有一个名为 ModelGroup 的对象,其中包含一个 ModelPerson 对象列表。我的目标是执行以下操作。

  1. 向服务器发送ModelGroup,得到一个响应,是一个整数,代表新插入的ID,姑且称之为newGroupId。
  2. 对于 ModelGroup 中的每个 ModelPerson,将 Person.groupId 设置为 newGroupId。
  3. 将每个人发送到服务器。
  4. 如果 ModelGroup 中的所有 ModelPerson 对象都已使用 newGroupId 成功更新,则响应 onSuccess,否则响应 onError。

我目前的解决方案如下所示。

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.
}

问题

如何使用 RxJava + Retrofit 解决方案实现相同(或更好)的功能?

编辑 1

MyApi 定义如下。

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

首先,您需要将 Retrofit beans 更改为使用 Observables。例如,它可能类似于以下行:

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

然后你可以链接请求:

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