如何创建rx.Single的缓存/热门版本?

时间:2015-08-07 10:26:29

标签: java reactive-programming rx-java kotlin

RxJava v1.0.13引入了新类型的Observable: rx.Single 。它非常适合请求 - 响应模型,但缺少引入doOnNext()等运算符的标准副作用。因此,结果会发生很多事情要困难得多。

我的想法是将doOnNext()替换为对同一Single实例的多个订阅。但这可能导致底层工作多次完成:每次订阅一次。

示例rx.Single implementation:

private class WorkerSubscribe<SomeData>() : Single.OnSubscribe<SomeData> {
    override fun call(sub: SingleSubscriber<in SomeData>) {
        try {
            val result = fetchSomeData()
            sub.onSuccess(result)
        } catch(t: Throwable) {
            sub.onError(t)
        }
    }
}

val single = Single.create<SomeData>(WorkerSubscribe())

用法:

single.subscribe({}, {})
single.subscribe({}, {})   // Data is fetched for the second time

是否有可能创建一个单独的实例,即使多次调用single.subscribe(),也不会多次fetchSomeData(),但缓存并返回相同的结果?

5 个答案:

答案 0 :(得分:3)

您需要RxJava SubjectdateStringBehaviorSubject

答案 1 :(得分:1)

我只需要类似的行为并找到一些解决方案。

您可以将Single转换为Observable申请cache(),然后将其转换回Single

yourSingle.toObservable().cacheWithInitialCapacity(1).toSingle()

我使用cacheWithInitialCapacity(1)代替cache()进行优化 - Single永远不会发出多个项目。

提供Transformer实施

也是个好主意
public class SingleUtils {

    public static <T> Single.Transformer<T, T> cached() {
        return single -> single.toObservable()
            .cacheWithInitialCapacity(1)
            .toSingle();
    }
}

所以你可以通过调用

在任何地方使用缓存
yourSingle.compose(SingleUtils.cached())

修改 从rxJava 1.2.2开始,它已被添加(https://github.com/ReactiveX/RxJava/releases/tag/v1.2.2

正是以这种方式实施的 (https://github.com/ReactiveX/RxJava/pull/4757

答案 2 :(得分:0)

Please check the cache() operator. It's supposed to cache the emissions from the Observable and reproduce them to the subsequent Subscribers.

答案 3 :(得分:0)

你可以创建一个BehaviorSubject / ReplaySubject / AsyncSubject - 然后在它上面调用。单击。

答案 4 :(得分:0)

我做了一些解决方法,我对它不满意但它有效:

public class Network {
   private Object data;
   private Single<Object> dataSingle;

   public Single<Object> getData {
      if (data == null) {
         if (dataSingle == null) {
            dataSingle = Single.create(...)
             .doOnSuccess( data -> this.data = data;)
             .sibscribeOn(..);
         }
         return dataSingle;
      } else {
         return Single.just(data);
      }
   }
}