rxjava interval()在某个事件之后重置时间

时间:2016-03-21 06:28:30

标签: java android rx-java rx-android

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

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

如果有办法解开&#34;取消合并&#34; intervalObservable,然后我可以将其取消合并到onNext中,然后再合并它。但似乎没有。 我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:12)

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

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秒继续更新。

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合并,只要单击刷新按钮,它就会出错。最后的retry将导致整个事件被重新订阅错误(按钮点击) - 导致它重新开始。

答案 1 :(得分:2)

最简单的解决方案不是每次点击按钮都取消订阅旧的observable并再次订阅?

   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();
    }
}