我怎么能用RxJava2简化这个多个依赖调用

时间:2017-08-18 14:25:11

标签: rx-java rx-java2

我想知道如何使用RxJava2执行以下操作,

  • 进行API调用以获取项目列表
  • 遍历项目列表
    • 如果项目是特定类型
      • 进行API调用以获取用户详细信息
      • 进行API调用以获取包含商品ID&的数据列表用户名(详情)
      • 遍历数据列表
        • 如果数据项代码与项目代码匹配(来自外部循环)
          • 通过将数据项复制到外部列表中来更新项目
  • 返回列表

我对RxJava很新,并尝试使用Single进行初始API调用,然后使用map运算符,然后在Mapper函数中,然后用其他内容完成正常的外环和内环。

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

2 个答案:

答案 0 :(得分:0)

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

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

并且内部循环可以是:

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

等等。我把事情分解为返回observables的嵌套函数调用,但是你可以将它们重新组合成一个可观察的链,这取决于你的代码风格和测试需求。

需要注意的要点:

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

答案 1 :(得分:0)

查看 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;
    }
}