我正在使用RX java进行工具中的大部分处理。基本上我正在研究的工具的想法是:
不确定图表是否可读,因此处理的伪代码如下所示:
Observable.just("SOME_PAYLOAD_AS_STRING")
.flatMap(payload -> splitToFragmentObservables(payload)) //Getting observables of fragments
.concatMapEager( //concat all processed fragments
fragment -> getServiceCallsObservable(fragment) //get service calls for all fragments
.flatMap(this::doServiceCall) // do service call
.reduce(new HashMap<>(), (all, result) -> { //reduce results into map
all.addAll(result);
return all;
})
.map(all -> newFragmentWithData(fragment, all)) //apply somehow the all service results to my fragment
)
.reduce(new StringBuilder(), StringBuilder::append) //reduce all fragments back to string
.map(StringBuilder::toString);
现在,我正在考虑如何改进某些处理,尤其是HTTP调用。正如您在图中可能注意到的那样,每个片段可以执行完全相同的调用(A,B或C),这是不必要的开销。
我正在寻找一种方法来避免在每个片段中进行相同的服务调用。改善它的最佳方法是什么?组合相同的呼叫,进行呼叫,然后在做最终结果时以某种方式使用它?或者做一些缓存?
答案 0 :(得分:1)
有一种方法可以缓存Observable
生成的结果,并为所有订阅者提供相同的结果。
您有两种选择:
cache
运算符。但是,你必须实现缓存失效。replay
和publish
运算符一起使用更复杂的解决方案。但是@JakeWharton已经应对了the solution这样的问题。 Here是对这个简单库的解释。额外: Here是为Observable发出相同值的问题的另一种解决方案。
希望,我理解了这个问题并给出了正确答案。
答案 1 :(得分:0)
使用Charles Proxy(或类似代码)查看实际正在进行的呼叫。
如果你使用一个好的Http库进行缓存,那么你的代码可能已经完美了。不要过早地优化!
根据端点具有的缓存规则(以及是否可以更改它们),您可以使用缓存结果来连续调用同一端点。如果您可以控制这些端点,则设置lenient缓存头。
向getServiceCallsObservable
添加缓存可能是一个更麻烦的解决方案。它还需要是线程安全的,因为getServiceCallsObservable
从不同的工作线程调用。 (至少应该,你可能需要添加一些额外的调度,具体取决于你的一些方法的实现和调度细节)
答案 2 :(得分:0)
感谢您的提示。实际上,当我在寻找使用番石榴缓存时,我找到了使用cache
运算符的优雅解决方案。
简单地映射到服务结果ObMapable的flatMap运算符
.flatMap(this::doServiceCall)
我改为使用guava cache get方法,当没有可用于给定键的值时执行回调
.flatMap(service -> cache.get(service.getUrl(), () -> doServiceCall(service.getUrl()).cache()))
所以我只是从服务调用中缓存缓存的observable。正在处理的每个新有效负载上正在重新初始化缓存 - 这种缓存仅用于请求。