使用concat()和first()来实现带有RxJava的缓存 - 并发调用

时间:2016-12-28 15:21:38

标签: java android rx-java

我正在使用RxJava以及concat()first()运算符:

public Observable<List<Entity>> getEntities() {
    invalidateCacheIfNeeded();
    return Observable
            .concat(cachedEntities(), networkEntities())
            .first();
}

cachedEntities返回从缓存列表构建的Observable,而networkEntities方法使用Retrofit获取实体。

除非两个用户快速订阅getEntities()返回的可观察量,否则这很有用。我猜第一次订阅的网络请求在第二次订阅时没有完成。在这种情况下,执行两个网络请求。我想避免的。

我尝试创建一个单线程调度程序,因此第二次调用的执行仅在第一次调用结束但没有运气时执行:

 mSingleThreadScheduler = Schedulers.from(Executors.newSingleThreadExecutor());

public Observable<List<Entity>> getEntities() {
    invalidateCacheIfNeeded();
    return Observable
            .concat(cachedEntities(), networkEntities())
            .subscribeOn(mSingleThreadScheduler)
            .first();
}

我已经尝试在Observable链中下调subscribeOn调用,但我得到了相同的结果。

任何提示?

3 个答案:

答案 0 :(得分:1)

我认为使方法线程安全不是一个好主意。因为它阻止了整个方法,从而降低了性能。因此建议使数据结构具有线程安全性。 在您的情况下,您在方法中使用列表

var array = [{id:123, value:"value1", name:"Name1"},
             {id:124, value:"value2", name:"Name1"},
             {id:125, value:"value3", name:"Name2"},
             {id:126, value:"value4", name:"Name2"}
            ],
result = array.reduce((p,c) => p[c.name] ? p : (p[c.name] = true, p.push(c.name), p), []);
console.log(result);

}

使用 CopyOnWriteArrayList 代替列表。它是线程安全的。

public Observable<List<Entity>> getEntities() {

}

希望它能奏效。

答案 1 :(得分:0)

这似乎是一个具有多个订阅者的可观察对象的相对常见的用例。你需要像

这样的东西
public Observable<List<Entity>> getEntities() {
    invalidateCacheIfNeeded();
    return Observable
            .concat(cachedEntities(), networkEntities())
            .first()
            .replay(1)            
}

查看this question的答案 更深入的解释。

答案 2 :(得分:0)

鉴于

public Observable<List<Entity>> getEntities() {
    invalidateCacheIfNeeded();
    return Observable
            .concat(cachedEntities(), networkEntities())
            .first();
}

您应该创建AsyncSubject<Data> mSubject并按照以下方式使用

private Observable<List<Entity>> networkEntities() {
    return mSubject
            .map(Data::getEntities);
}

您的网络通话应该如下所示

public Observable<Data> getDataFromNetwork() {
    return networkOperation()
            .subscribeOn(mSingleThreadScheduler)
            .subscribe(mSubject);
}