【问题标题】:How could I simplify this multiple dependent calls with RxJava2如何使用 RxJava2 简化多个依赖调用
【发布时间】:2017-08-21 01:57:44
【问题描述】:

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

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

我对 RxJava 很陌生,并尝试使用 Single 进行初始 API 调用,然后使用 map 运算符,然后在 Mapper 函数中使用正常的外部和内部来完成其余的工作循环。

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

【问题讨论】:

  • 请提供您的模型类

标签: rx-java rx-java2


【解决方案1】:

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

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();当您需要将 observable 转换为它产生的值时,请使用 flatMap()

【讨论】:

  • 谢谢你会试一试并回复。顺便说一句,您知道使用Single 时是否也一样?
  • 使用Single 而不是Observable 来表示checkItemAndReplace() 的问题在于,您必须将其转换为Observable 以用于flatMap() 运算符。如果getUpdatesForItem() 返回一个Single,那么您需要在return 语句中将其转换为Observable
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2018-06-20
    • 2021-12-30
    • 2020-02-29
    • 1970-01-01
    • 1970-01-01
    • 2016-03-02
    • 2021-05-22
    • 1970-01-01
    • 2019-06-07
    相关资源
    最近更新 更多