【问题标题】:Merging data from different Observables, and choosing different fetching strategies, depending on data availability合并来自不同 Observable 的数据,并根据数据可用性选择不同的获取策略
【发布时间】:2016-06-05 19:25:50
【问题描述】:

我有一种情况,通过获取 Item 对象,应该会发生以下三件事之一:

  • 如果缓存中不存在该项(a.k.a 为 null),则从 api1api2 加载数据,合并数据并返回 Observable
  • 如果该项目存在于缓存中,但缺少某部分,则从api2 加载数据,并将其与缓存中已有的数据合并
  • 如果缓存中的所有数据都可用,只需返回即可。

到目前为止,这是我想出的最好的:

val cacheObservable = cache.fetchItem(itemId);
val api1Observable = api1.fetchItem(itemId);
val api2Observable = api2.fetchItem(itemId);

val resultObservable = cacheObservable!!.flatMap { item: Item? ->
    if (item == null) {
        /* Get the item data, and the full text separately, then combine them */
        Observable.zip(api1Observable, api2Observable, { itemData, itemText ->
            itemData.apply { text = itemText }
        });
    } else if (item.text.isNullOrEmpty()) {
        /* Get the full text only, then add it to the already cached version */
        cacheObservable.zipWith(api2Observable, { cachedItem, itemText -> cachedItem.apply { text = itemText; } });
    } else {
        /* if the data and the full text are provided, simply return */
        Observable.just(item);
    }
}.doOnNext { item -> cache.saveOrUpdateItem(item); }

return resultObservable;

到目前为止,这工作正常,但我一直想知道,是否有更声明的方式来实现相同的效果。欢迎提出建议。

【问题讨论】:

  • 您的fetchItem 函数可以返回错误而不是null,因此您可以使用错误处理运算符而不是检查空值。

标签: android rx-java kotlin observable


【解决方案1】:

我不知道 Kotlin 语法,但这里有一个你可以翻译的 Java 示例。当项目不在缓存中时,它需要 cache.fetchItem(itemId) 来完成,而不是发出 null

如果cacheFetch 发出一个项目,flatMap() 将确保该项目具有文本并在需要时从网络获取它。

如果缓存中没有任何内容,fullFetch 将从网络中获取。

concatWith(fullFetch).take(1) 将确保 fullFetch 仅在缓存中没有任何内容时订阅。

该项目仅在更新后才保存到缓存中。

Observable<Item> cacheFetch = cache.fetchItem(itemId);
Observable<Item> fullFetch =
  Observable
    .zip(
      api1.fetchItem(itemId),
      api2.fetchItem(itemId),
      (item, itemText) -> {
          item.text = itemText;
          return item;
      })
    .doOnNext(cache::saveOrUpdateItem);

Observable<Item> resultObservable =
  cacheFetch
    .flatMap(item -> {
      if (item.text != null && !item.text.isEmpty()) {
        return Observable.just(item);
      }
      return api2
        .fetchItem(itemId)
        .map(itemText -> {
          item.text = itemText;
          return item;
        })
        .doOnNext(cache::saveOrUpdateItem);
    })
    .concatWith(fullFetch)
    .take(1);
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-04
    • 1970-01-01
    • 1970-01-01
    • 2019-06-09
    • 1970-01-01
    相关资源
    最近更新 更多