如何使用 RxJava2 简化此多个依赖调用



我想知道如何用RxJava2执行类似以下内容的事情,

  • 进行 API 调用以获取项目列表
  • 循环访问项目列表
    • 如果项目属于特定类型
      • 进行 API 调用以获取用户详细信息
      • 进行 API 调用以获取包含项目 ID 和用户名的数据列表(来自详细信息(
      • 循环访问数据列表
        • 如果数据项代码与项代码匹配(从外部循环(
          • 通过向外部列表复制数据项来更新外部列表中的项
  • 返回列表

我是 RxJava 的新手,并尝试使用初始 API 调用的Single执行此操作,然后使用map运算符,然后在 Mapper 函数中使用正常的外部和内部循环完成其余工作。

我真的很想知道映射器功能部分是否也可以以某种方式以更简单的方式使用 RxJava 而不是使用嵌套循环来完成?

您的外部循环可能如下所示:

Observable.fromIterable( list )
.flatMap( item -> checkItemAndReplace( item ) )
.toList();

内部循环可以是:

Observable<ItemType> checkItemAndReplace( ItemType item ) {
if ( isItemOfSpecificType( item ) ) {
return getUpdatesForItem( item );
}
return Observable.just( item );
}

以此类推,用于内部循环。我将内容分解为返回可观察量的嵌套函数调用,但您可以根据代码风格和测试需求将它们重新组合到可观察链中。

注意事项:

  1. 您可以使用各种可观察运算符与普通数据结构进行转换。fromIterable()just()转换为可观察量,而toList()则转换回列表。
  2. 当操作从一个值转换为另一个值或将一个不可观察值转换为另一个值时,请使用map();当需要将可观察量转换为它生成的值时,请使用flatMap()

看看API界面和itemsToBeRefreshed Observable。您可以使用Observable.fromIterable来迭代列表和flatMap来链接不同的 api 调用。此外,如果您有请求-响应行为,则应使用 Single 作为返回类型。此外,不要更改流中项的属性。只需将要更改的项目复制到新对象并将它们写回即可。

@Test
public void name() throws Exception {
Api api = mock(Api.class);
when(api.getItems()).thenReturn(Single.just(Arrays.asList(
new Item(0, 123),
new Item(1, 123),
new Item(2, 333)
)));
when(api.getUserDetails(eq(0))).thenReturn(Single.just(new UserDetails("hans wurst", 0)));
when(api.getUserDetails(eq(1))).thenReturn(Single.just(new UserDetails("mett wurst", 1)));
when(api.getUserDetails(eq(2))).thenReturn(Single.just(new UserDetails("kaese wurst", 2)));
when(api.getData(eq(0), eq("hans wurst"))).thenReturn(Single.just(new Data(123)));
when(api.getData(eq(1), eq("mett wurst"))).thenReturn(Single.just(new Data(123)));
when(api.getData(eq(2), eq("kaese wurst"))).thenReturn(Single.just(new Data(666)));
Observable<Item> itemsToBeRefreshed = api.getItems()
.flatMapObservable(strings -> Observable.fromIterable(strings))
.filter(s -> s instanceof Item) // test for specific type
.flatMapMaybe(item -> api.getUserDetails(item.id)
.flatMap(userDetails -> api.getData(userDetails.id, userDetails.userName))
.filter(data -> data.code == item.code)
.map(data -> new Item(-1, -1)) // create new Item and copy properties over from data
);
itemsToBeRefreshed.test()
.assertValueCount(2);
// subscribe to 'itemsToBeRefreshed' in order to write back items or just chain it to itemsToBeRefreshed with doOnNext
}
interface Api {
Single<List<Item>> getItems();
Single<UserDetails> getUserDetails(int id);
Single<Data> getData(int id, String userName);
}
class Item {
int id;
int code;
Item(int id, int code) {
this.id = id;
this.code = code;
}
}
class UserDetails {
String userName;
int id;
UserDetails(String userName, int id) {
this.userName = userName;
this.id = id;
}
}
class Data {
int code;
Data(int code) {
this.code = code;
}
}

最新更新