合并来自不同Observable的数据,并根据数据可用性选择不同的获取策略
我有一种情况,通过获取一个Item
对象,三件事情之一应该发生:
- 如果该项目不存在于缓存(又名为空)中,则从
api1
和api2
加载数据,合并数据并返回一个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); }