合并来自不同Observable的数据,并根据数据可用性选择不同的获取策略

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

  • 如果该项目不存在于缓存(又名为空)中,则从api1api2加载数据,合并数据并返回一个Observable
  • 如果该项目存在于缓存中,但缺少api2 ,则从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; 

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

我不知道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); }