我正在制作一个带有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
中,然后再合并它。但似乎没有。
我怎样才能做到这一点?
答案 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();
}
}