RxJava2具有可观察的远程数据覆盖本地数据

时间:2018-11-20 01:01:54

标签: caching observable rx-java2

当前,我在存储库类中有一个方法,该方法可从本地缓存和远程API提取数据。

public Observable<List<Items>> getItemsForUser(String userId {
    return Observable.concatArrayEager(
            getUserItemsLocal(userId), // returns Observable<List<Items>>
            getUserItemsRemote(userId) // returns Observable<List<Items>>
    );
}

当前,该方法首先获取本地数据(可能已过时)并返回它,然后使用来自远程API的新数据对其进行更新。

我想将实现更改为使用Observable.merge,以便如果远程API请求首先完成,则首先显示该数据。但是,如果我只使用Observable.merge,则会担心本地数据库请求可能会返回陈旧的数据,然后该数据将覆盖远程的新数据。

基本上,我想要类似的东西:

public Observable<List<ShoutContent>> getItemsForUser(String userId, ErrorCallback errorCallback) {
    return Observable.merge(
            getUserItemsRemote(userId),
            getUserItemsLocal(userId)
                .useOnlyIfFirstResponse()
}

因此,如果远程API请求首先完成,则该响应是唯一返回的响应。但是,如果本地请求首先完成,则我想返回该请求,然后在完成后返回远程请求。 RxJava是否有内置的类似内容?

编辑:我想补充一点,getUserItemsRemote确实在Observable发出时更新了本地数据库,但是我认为我无法确保在本地请求完成之前将数据库更新,这使得本地请求将以陈旧数据响应的可能性。

1 个答案:

答案 0 :(得分:0)

您可以使用takeUntil运算符。

takeUntil返回一个Observable,它发出由源Observable发出的项目,直到第二个ObservableSource发出一个项目为止。

在您的情况下,一旦发出远程Observable,您就必须停止观察本地可观察对象。该代码如下所示。

public Observable<String> getUserItemsLocal() {
    return Observable.just("Local db response")
            .delay(5, TimeUnit.SECONDS);  // assume local db takes 5 seconds to emit
}


public Observable<String> getUserItemsRemote() {
    return Observable.just("Remote Data")
            .delay(1, TimeUnit.SECONDS); // remote data comes quicker, in 1 second
}

您的存储库代码类似

Observable<String> remoteResponse = getUserItemsRemote();
getUserItemsLocal().takeUntil(remoteResponse)
            .mergeWith(remoteResponse)
            .subscribe(new Consumer<String>() {
                @Override
                public void accept(String s) throws Exception {
                    Log.d(TAG, "result: " + s);
                }
            });