我使用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();
}
}
}
我使用此类在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();
当从计时器中选择onFinish(),从片段中选择onDestroyView,以及片段代码中的其他位置时,我将其称为:
if(timer != null){
timer.cancel();
}
从记录中我可以看到cancel()被调用并被丢弃。但是,即使像在第二个代码示例中所示重置计时器(我有一个类变量Countdowntimer计时器)一样,我也可以看到旧计时器仍处于活动状态并更新进度条(旧计时器和新计时器都更新进度条,因此进度会在这两个值之间跳跃)。
我不明白这一点,为什么计时器没有完全处理掉?为什么“旧计时器”仍然继续更新值?
编辑:
这是计时器类在片段中的行为:
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
它将继续“堆叠”更多的计时器(我称之为dispose())...
答案 0 :(得分:2)
我不确定您为什么要这样做,但是有一个运算符intervalRange
可以用更少的步骤来解决这个问题。如果您要重复使用相同的Countdowntimer
,则管理一次性用品可能会成为一个问题。试试这个:
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);
}
}
答案 1 :(得分:0)
也尝试通过GC清除实例。将以下内容添加到要呼叫timer.cancel()
的所有位置。将其设置为null将通知GC该计时器实例已准备好清除。
if(timer != null) {
timer.cancel();
timer= null;
}