Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/199.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android RxJava运营商喜欢重播(1,1,分钟),但在1分钟后重新订阅_Android_Kotlin_Rx Java_Reactive Programming_Rx Java2 - Fatal编程技术网

Android RxJava运营商喜欢重播(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{}合并的东西,但找不到它。我

我需要一个相对简单的过期缓存机制(比如1分钟)

  • 当第一个订户订阅时,我想进行API调用
  • 当第二个用户在分钟内订阅时,不希望进行API调用,而是将先前加载的值推送到下游
  • 当另一个用户在距第一个用户一分钟后订阅时,我希望再次进行API调用

  • 现在,我想在一个rxjava链中实现这一点
    .replay(1,1,分钟)
    看起来很完美,直到我了解到,在一分钟过去后,源观测值没有被重新订阅。我再也没有从那个可观察的东西中得到任何东西。我可能需要将
    replay()
    repeatWhen{}
    合并的东西,但找不到它。我尝试了非常奇特的组合,但没有一个适合我的测试用例。

    您可以使用以下运算符

  • .retryWhen()运算符以重新订阅
  • (()运算符延迟订阅者:延迟运算符通过在发出每个源可观察项之前暂停特定的时间增量(您指定)来修改其源可观察项。这具有将可观测对象发射的整个项目序列在时间上向前移动指定增量的效果

  • 这可能不是最好的解决方案,但我会尝试这样做:

        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