我建议采取稍微不同的方法。实际上,我们正在寻找的是两次点击之间的时间。 RxJava有运算符间隔(时间单位) http://reactivex.io/documentation/operators/timeinterval.html,这正是我们想要的。
因此,我们有了主题和所需的退出超时。
private static final long EXIT_TIMEOUT = 2000;
private CompositeDisposable compositeDisposable = new CompositeDisposable();
private PublishSubject<Boolean> backButtonClickSource = PublishSubject.create();
在 onResume 中,我们向主题添加运算符并订阅它。我们将结果添加到 CompositeDisposable 中,以便稍后能够将其与您可能在活动中拥有的所有其他订阅一起处置。
@Override
protected void onResume() {
super.onResume();
compositeDisposable.add(backButtonClickSource
.debounce(100, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(new Consumer<Boolean>() {
@Override
public void accept(@NonNull Boolean event) throws Exception {
Toast.makeText(MainActivity.this, "Please press back once more to exit", Toast.LENGTH_SHORT).show();
}
})
.timeInterval(TimeUnit.MILLISECONDS)
.skip(1)
.filter(new Predicate<Timed<Boolean>>() {
@Override
public boolean test(@NonNull Timed<Boolean> interval) throws Exception {
return interval.time() < EXIT_TIMEOUT;
}
})
.subscribe(new Consumer<Timed<Boolean>>() {
@Override
public void accept(@NonNull Timed<Boolean> interval) throws Exception {
finish();
}
}));
}
我们使用去抖来消除噪音(也许不必要)。然后,每次单击时,我们都会向用户显示消息(无论您想要什么,为了简单起见,我使用了 Toast)。在切换到主线程之前,否则会抛出异常。我们跳过第一个事件,因为否则订阅和第一次单击之间的时间间隔将被发出,如果它足够小,只需单击一次就会退出。我们过滤掉所有大于 EXIT_TIMEOUT 的间隔。最后,当我们获得足够小的时间间隔(这不是第一个)时,我们完成我们的活动。
然后,在 onPause 中,我们应该清除 CompositeDisposable,以便不再获取点击事件。
@Override
protected void onPause() {
super.onPause();
compositeDisposable.clear();
}
当然,在 onBackPressed() 中,我们应该将后退按钮点击转发给我们的 PublishSubject。
@Override
public void onBackPressed() {
backButtonClickSource.onNext(true);
}