关于java:rxjava interval()在某些事件后的重置时间

rxjava interval() reset time after some event

我正在用RxJava制作一个Android应用程序,在其中一个页面中,我有一个按钮,当按下该按钮时,页面将刷新。 而且我还希望每10秒自动刷新一次,前提是用户在这段时间内没有按下按钮。 但是,当用户单击按钮时,我希望自动刷新动作在单击后10秒钟后发生。 而不是继续自己的10秒间隔。
例如,在第二秒0时,应用程序执行自动刷新,然后在第二秒3时,用户按下按钮。 然后,自动刷新应在第13、23、23等发生。
我知道有一个interval()运算符,它以一定的间隔发射项目。 但是似乎没有办法"重置"开始时间。 有点像退订并再次订阅interval() Observable。 一段代码就像

1
2
3
4
Observable<Long> intervalObservable = Observable.inteval(10, TimeUnit.SECONDS)
RxView.click(refreshButton).map(ignored -> 0L)
      .merge(intervalObservable)
      .subscibe(ignore -> performRefresh());

如果有一种方法可以"取消合并" intervalObservable,则可以将其取消合并到onNext中,然后再次合并。 但似乎没有。
我该如何实现?


您可以使用switchMap运算符很好地完成此操作。每次按下按钮,它将切换到可观察间隔的新订阅-这意味着它将重新开始。先前的订阅会自动删除,因此不会运行多个时间间隔。

1
2
3
4
5
6
7
8
9
10
Observable<Long> intervalObservable = Observable.interval(10, TimeUnit.SECONDS);

RxView.clicks(refreshButton)
    .switchMap(ignored -> {
        return intervalObservable
            .startWith(0L)                 // For an immediate refresh
            .observeOn(AndroidSchedulers.mainThread())
            .doOnNext(x -> performRefresh());
    })      
    .subscribe();

startWith向间隔添加一个立即值(单击按钮时立即刷新),observeOn确保刷新在主线程上进行(因为间隔将在后台线程上发出,所以很重要)。

更新:vman注意到该实现仅在用户第一次单击按钮后才开始刷新。以下替代方法将在订阅后立即刷新,然后每10秒钟刷新一次,直到单击该按钮为止;此时,它将再次立即刷新,然后每10秒钟继续更新一次。

1
2
3
4
5
6
7
8
9
10
11
12
Observable<Long> intervalObservable = Observable.interval(10, TimeUnit.SECONDS)
    .startWith(0L)  // For an immediate refresh
    .observeOn(AndroidSchedulers.mainThread())
    .doOnNext(x -> performRefresh());

Observable<Long> buttonClickedObservable = RxView.clicks(refreshButton)
    .map(e -> 0L)  // To make the compiler happy
    .switchMap(ignored -> Observable.error(new RuntimeException("button pressed")));

Observable.merge(intervalObservable, buttonClickedObservable)
    .retry()
    .subscribe();

在此实现中,进行刷新的Observable立即被订阅(导致立即刷新,并每10秒重复一次),它与Observable合并,每当单击刷新按钮时,该Observable都会出错。最后的retry会导致整个事情因错误(单击按钮)而被重新订阅-导致一切重新开始。


最简单的解决方案是不是您每次单击按钮都取消订阅旧的可观察项并再次订阅?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
   Subscription subscription= null;  
   Observable<Long> interval = nul;


 public void subscribe(){

    interval = Observable
            .interval(10000L, TimeUnit.MILLISECONDS);
    subscription = interval.subscribe(item -> System.out.println("doing something"));

}

public void eventClick(){
    if(clickButtin){
        subscription.unsubscribe();
        subscribe();
    }
}