Android RxJava运营商喜欢重播(1,1,分钟),但在1分钟后重新订阅
我需要一个相对简单的过期缓存机制(比如1分钟)Android RxJava运营商喜欢重播(1,1,分钟),但在1分钟后重新订阅,android,kotlin,rx-java,reactive-programming,rx-java2,Android,Kotlin,Rx Java,Reactive Programming,Rx Java2,我需要一个相对简单的过期缓存机制(比如1分钟) 当第一个订户订阅时,我想进行API调用 当第二个用户在分钟内订阅时,不希望进行API调用,而是将先前加载的值推送到下游 当另一个用户在距第一个用户一分钟后订阅时,我希望再次进行API调用 现在,我想在一个rxjava链中实现这一点.replay(1,1,分钟)看起来很完美,直到我了解到,在一分钟过去后,源观测值没有被重新订阅。我再也没有从那个可观察的东西中得到任何东西。我可能需要将replay()与repeatWhen{}合并的东西,但找不到它。我
现在,我想在一个rxjava链中实现这一点
.replay(1,1,分钟)
看起来很完美,直到我了解到,在一分钟过去后,源观测值没有被重新订阅。我再也没有从那个可观察的东西中得到任何东西。我可能需要将replay()
与repeatWhen{}
合并的东西,但找不到它。我尝试了非常奇特的组合,但没有一个适合我的测试用例。您可以使用以下运算符
这可能不是最好的解决方案,但我会尝试这样做:
public final class SimpleCacheSingle<T : Any> constructor(
val apiRequest: (value: String, callback: (T) -> Unit) -> Unit
) {
private var lastTimeSeconds = 0L
private lateinit var cachedValue: T
fun getSingle(): Single<T> = Single.create { emitter ->
if (System.currentTimeMillis() / 1000 - lastTimeSeconds > 60) {
apiRequest("example argument") {
cachedValue = it
lastTimeSeconds = System.currentTimeMillis() / 1000
emitter.onSuccess(cachedValue)
}
} else {
emitter.onSuccess(cachedValue)
}
}
}
public final类SimpleCacheSingle构造函数(
val APIRESQUEST:(值:字符串,回调:(T)->Unit)->Unit
) {
私有变量lastTimeSeconds=0L
私有lateinit var cachedValue:T
fun getSingle():Single=Single.create{emitter->
如果(System.currentTimeMillis()/1000-lastTimeSeconds>60){
apiRequest(“示例参数”){
cachedValue=it
lastTimeSeconds=System.currentTimeMillis()/1000
发射器.onSuccess(缓存值)
}
}否则{
发射器.onSuccess(缓存值)
}
}
}
只需创建它的一个实例,并使用getSingle()为每个订阅服务器创建single
当然,附件代码段中的“apiRequest”需要修改以满足您的需要
编辑:
请注意,当您在上一个api调用完成之前订阅时,您将有两个或多个挂起的api请求,而不是一个。
您必须修改代码,以便一次只能有一个请求。我认为此代码(此处的时间间隔为5秒,而不是1分钟。测试更容易)应该可以做到:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss").withZone(ZoneId.systemDefault());
AtomicInteger subscriberCounter = new AtomicInteger(0);
PublishProcessor<String> repeater = PublishProcessor.create();
Flowable<String> flowable =
Flowable.defer(() -> Flowable.just(apiCall()))
.repeatWhen(handler -> repeater
.skip(5, SECONDS) // don't trigger a repeat for any new subscription between 0 and 5 seconds
.throttleFirst(5, SECONDS) // trigger a repeat and ignore any new notification during 5 sec
)
.replay(1)
.autoConnect()
.doOnSubscribe(s -> {
System.out.println(formatter.format(now())
+ " -----> new subscription of subscriber #"
+ subscriberCounter.incrementAndGet());
repeater.onNext("whatever"); // notify a new subscription to the repeat handler
});
flowable.subscribe(s ->System.out.println("subscriber #1 receives: " + s));
Thread.sleep(3000);
flowable.subscribe(s -> System.out.println("subscriber #2 receives: " + s));
Thread.sleep(4000);
flowable.subscribe(s -> System.out.println("subscriber #3 receives: " + s));
Thread.sleep(100);
flowable.subscribe(s -> System.out.println("subscriber #4 receives: " + s));
Thread.sleep(6000);
flowable.subscribe(s -> System.out.println("subscriber #5 receives: " + s));
Thread.sleep(1000);
flowable.subscribe(s -> System.out.println("subscriber #6 receives: " + s));
Thread.sleep(6000);
flowable.subscribe(s -> System.out.println("subscriber #7 receives: " + s));
Flowable.timer(60, SECONDS) // Just to block the main thread for a while
.blockingSubscribe();
也许我们可以做得更好,但我现在没有其他想法。出错后重试重新订阅。拖延只会让我更加等待结果。它们不提供任何缓存功能,除非我遗漏了什么。您是否尝试将
.interval(1,分钟)
与.replay(1,1,分钟)
结合使用interval()
每分钟进行一次API调用。问题是我不想每分钟进行一次调用。我只想在需要的时候打电话,但不超过一分钟。谢谢@Dominik Setniewski,这当然会奏效,但我想要一个优雅的单链解决方案。不过,这可能不是一个简单的方法。
16:54:54 -----> new subscription of subscriber #1
subscriber #1 receives: API call #0
16:54:57 -----> new subscription of subscriber #2
subscriber #2 receives: API call #0
16:55:01 -----> new subscription of subscriber #3
subscriber #1 receives: API call #1
subscriber #2 receives: API call #1
subscriber #3 receives: API call #1
16:55:01 -----> new subscription of subscriber #4
subscriber #4 receives: API call #1
16:55:07 -----> new subscription of subscriber #5
subscriber #1 receives: API call #2
subscriber #2 receives: API call #2
subscriber #3 receives: API call #2
subscriber #4 receives: API call #2
subscriber #5 receives: API call #2
16:55:08 -----> new subscription of subscriber #6
subscriber #6 receives: API call #2
16:55:14 -----> new subscription of subscriber #7
subscriber #1 receives: API call #3
subscriber #2 receives: API call #3
subscriber #3 receives: API call #3
subscriber #4 receives: API call #3
subscriber #5 receives: API call #3
subscriber #6 receives: API call #3
subscriber #7 receives: API call #3