[英]RxJava custom countdowntimer continues to “tick” after disposed
I made a simple timer class using RxJava Observables: 我使用RxJava Observables创建了一个简单的计时器类:
public abstract class CountDownTimer {
private final TimeUnit timeUnit;
private final Long startValue;
private Disposable disposable;
public CountDownTimer(Long startValue, TimeUnit timeUnit) {
this.timeUnit = timeUnit;
this.startValue = startValue;
}
public abstract void onTick(long tickValue);
public abstract void onFinish();
public void start(){
Observable.zip(
Observable.range(0, startValue.intValue()),
Observable.interval(1, timeUnit),
(integer, aLong) -> startValue - integer)
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
disposable = d;
}
@Override
public void onNext(Long aLong) {
onTick(aLong);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
onFinish();
}
});
}
public void cancel(){
if(disposable!=null) {
disposable.dispose();
}
}
}
I use this class to set progress on a ProgressBar
(initiation from a method in Fragment
): 我使用此类在ProgressBar
上设置进度(从Fragment
的方法初始化):
timer = new CountDownTimer(QUESTION_TIME, TimeUnit.SECONDS) {
@Override
public void onTick(long tickValue) {
//set progress color
}
@Override
public void onFinish() {
//set progress color
}
};
timer.start();
When onFinish() tick from timer, onDestroyView from fragment, and other places in my fragment code, I call this: 当onFinish()从计时器开始计时,onDestroyView从片段开始计时,以及片段代码中的其他位置时,我将其称为:
if(timer != null){
timer.cancel();
}
And I can see from logging that cancel() is called and it is disposed of. 从记录中可以看到cancel()被调用并被丢弃。 However, even when resetting timer (I have a class variable Countdowntimer timer) like I showns in my second code example, I can see that the old timer is still active and updates the progressbar (both the old, and new timer updates the progressbar, so progress jumps between these 2 values). 但是,即使像我在第二个代码示例中所示重置计时器(我有一个类变量Countdowntimer计时器)一样,我也可以看到旧计时器仍处于活动状态并更新进度条(旧计时器和新计时器都更新进度条,因此进度会在这两个值之间跳跃)。
I don't understand this, why is the timer not completly disposed of? 我不明白,为什么计时器没有完全处理掉? Why does the "old timer" still continue to update the values? 为什么“旧计时器”仍然继续更新值?
EDIT: 编辑:
This is how the timer class behaves in a fragment: 这是计时器类在片段中的行为:
TICK 25 //first call to create new timer
TICK 24
TICK 23
TICK 22
TICK 21
TIMER CANCELLED //first call stopped. timer.cancel() called (which then calls disposable.dispose() in CountDownTimer.class)
TICK 25 //second call
TICK 25 // somehow the first call also start again?
TICK 24
TICK 24
TICK 23
TICK 23
TICK 22
TICK 22
TIMER CANCELLED //cancel second call
TICK 21 //first or second call still continues
TICK 20
TICK 19
TICK 18
And it will continue to "stack on" more timers (which I called dispose() on)... 而且它将继续“堆叠”更多的计时器(我称之为dispose())。
I'm not sure why you do this in this way, but there is an operator intervalRange
that gets you this in fewer steps. 我不确定为什么要用这种方法,但是有一个运算符intervalRange
可以使您以更少的步骤完成此操作。 Also managing the disposable could be a problem if you are reusing the same Countdowntimer
. 如果您要重复使用相同的Countdowntimer
则管理一次性物品可能会有问题。 Try this: 尝试这个:
class CountdownTimer {
SerialDisposable disposable = new SerialDisposable();
//...
public void start() {
disposable.set(
Observable.intervalRange(0, startValue,
1, timeUnit, AndroidSchedulers.mainThread())
.subscribe(
tick -> onTick(startValue - tick)
error -> error.printStackTrace()
() -> onFinish()
)
);
}
public void cancel() {
disposable.set(null);
}
}
Try to clear the instance through GC too. 也尝试通过GC清除实例。 add the following to all the places where you are calling timer.cancel()
. 将以下内容添加到要调用timer.cancel()
所有位置。 Setting it to null will notify the GC that the timer instance is ready to be cleared. 将其设置为null将通知GC该计时器实例已准备好被清除。
if(timer != null) {
timer.cancel();
timer= null;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.