【问题标题】:RxJava network requests and cachingRxJava 网络请求和缓存
【发布时间】:2016-01-20 22:07:07
【问题描述】:

我正在寻找一个我尝试在 RxJava 的帮助下实现的流程示例。

假设我想显示一个数据列表。流程应如下所示:

  1. 读取缓存。如果它包含数据,则显示它;
  2. 向服务器发送 API 请求:

    如果返回数据,则缓存并显示。

    如果返回错误并且没有缓存数据,则显示错误。

    如果它返回错误并且缓存了某些内容,则什么也不做。

现在我有一个method that does something similar(从Jake's u2020 获得了很多灵感)。主要区别在于它使用内存缓存,这意味着不需要单独的Observable 来从缓存中读取,并且可以同步完成。

我不知道如何组合两个可观察对象(一个用于从缓存中读取,另一个用于 API 调用)并获得上述流程。

有什么建议吗?

【问题讨论】:

  • 看起来你需要amb: github.com/ReactiveX/RxJava/wiki/…
  • @zsxwing 你能举个例子吗?我愿意接受建议,即使我找到了答案(这并不完美)。
  • 我倾向于将缓存处理留给网络客户端。如果您使用 HTTP,则响应中的标头专用于指示客户端应实现哪种类型的缓存,对象应保留多长时间......更不用说还有可能验证您的缓存是仍然有效并在必要时更新(返回代码 304)。
  • @EgorN 我想你想要第一个返回的 Observable 的结果,无论是来自缓存还是服务器。如果是这样,您可以使用amb(readDataFromCache(), apiCall())
  • @zsxwing 这不是我真正想要的。我希望它先显示缓存数据,然后如果服务器的响应正常,则显示来自服务器的更新数据。

标签: android rx-java


【解决方案1】:

我想我解决了我的问题。可观察链如下所示:

apiCall()
        .map(data -> dataInMemory = data)
        .onErrorResumeNext(t -> data == null ?
                Observable.just(Data.empty()) : Observable.empty())
        .startWith(readDataFromCache().map(data -> dataInMemory = data))
        .subscribeOn(ioScheduler)
        .observeOn(uiScheduler)
        .subscribe(dataRequest);

重点是,如果readDataFromCache() 抛出错误,它将调用onCompleted() 而不会调用onError()。所以它应该是一个你可以控制的自定义Observable

Data.empty() 是我的数据的存根 - Subscriber 应将其视为错误。

dataInMemory 是我的控制器中的一个成员,它充当内存缓存。


编辑:该解决方案无法正常工作。没有完成一个用例(见评论)。

编辑 2: 好吧,解决方案确实经过一些调整后可以正常工作。该修复程序根据内存中缓存的状态返回不同类型的 observables。有点脏。

【讨论】:

  • 好吧,我的解决方案不起作用。如果readDataFromCache() 运行良好并显示一些数据,而apiCall() 返回错误,则显示错误。
【解决方案2】:

这是我的解决方案:

readDataFromCache().defaultIfEmpty(null)
        .flatMap(new Func1<Data, Observable<Data>>() {

            @Override
            public Observable<Data> call(final Data data) {
                if (data == null) {
                    // no cache, show the data from network or throw an error
                    return apiCall();
                } else {
                    return Observable.concat(
                            Observable.just(data),
                            // something cached, show the data from network or do nothing.
                            apiCall().onErrorResumeNext(Observable.<Data>empty()));
                }
            }
        });

我没有添加subscribeOnobserveOn,因为我不确定readDataFromCache() 应该使用ioScheduler 还是uiScheduler

【讨论】:

  • 我遇到的唯一问题是readDataFromCache() 返回错误。 onErrorResumeNext(Observable.&lt;Data&gt;empty()) 应该在 defaultIfEmpty(null) 之前添加以消除错误。
猜你喜欢
  • 1970-01-01
  • 2018-08-19
  • 2017-03-13
  • 1970-01-01
  • 2021-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多