RxJava Retrofit 带有 foreach 循环的请求链
RxJava Retrofit chain of requests with foreach loop
我正在尝试从使用普通 Retrofit 迁移到使用 RxJava 扩展进行改造,以便在后台线程上进行 API 调用链。
例如,我有一个名为 ModelGroup 的对象,其中包含一个 ModelPerson 对象列表。我的目标是执行以下操作。
- 向服务器发送ModelGroup,得到一个响应,是一个整数,代表新插入的ID,姑且称之为newGroupId。
- 对于 ModelGroup 中的每个 ModelPerson,将 Person.groupId 设置为 newGroupId。
- 将每个人发送到服务器。
- 如果 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());
}
我正在尝试从使用普通 Retrofit 迁移到使用 RxJava 扩展进行改造,以便在后台线程上进行 API 调用链。
例如,我有一个名为 ModelGroup 的对象,其中包含一个 ModelPerson 对象列表。我的目标是执行以下操作。
- 向服务器发送ModelGroup,得到一个响应,是一个整数,代表新插入的ID,姑且称之为newGroupId。
- 对于 ModelGroup 中的每个 ModelPerson,将 Person.groupId 设置为 newGroupId。
- 将每个人发送到服务器。
- 如果 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());
}