java.lang.IllegalStateException Task already scheduled or cancelled出现的原因主要是是因为Timer
和TimerTask
都是一次性的消耗品,在调用cancle
之后再次进行任务调度时就需要重新new新的timer
和task
。
解决方法如下:
方法一:
在调用Timer
的cancle
方法后,需要重新new新的timer
和task
。如下
private void initCursorTimer() {
mCursorTimerTask = new TimerTask() {
@Override
public void run() {
// 通过光标间歇性显示实现闪烁效果
isCursorShowing = !isCursorShowing;
postInvalidate();
}
};
mCursorTimer = new Timer();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
initCursorTimer();
// 启动定时任务,定时刷新实现光标闪烁
mCursorTimer.scheduleAtFixedRate(mCursorTimerTask, 0, mCursorDuration);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mCursorTimer != null) {
mCursorTimer.cancel();
mCursorTimer.purge();
mCursorTimer = null;
}
}
这里需要注意的是调用timer的cancle方法时,还需要调用purge方法
- 方法二:
调用TimerTask
的cancle
方法,不需要重新new一个timer
出来,即所有的task共用同一个timer
。
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mCursorTimerTask = new TimerTask() {
@Override
public void run() {
// 通过光标间歇性显示实现闪烁效果
isCursorShowing = !isCursorShowing;
postInvalidate();
}
};
// 启动定时任务,定时刷新实现光标闪烁
mCursorTimer.scheduleAtFixedRate(mCursorTimerTask, 0, mCursorDuration);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mCursorTimerTask != null) {
mCursorTimerTask.cancel();
mCursorTimerTask = null;
}
}
- 两个
cancle
方法的区别是TimerTask
类还是Timer
类,cancel
方法都是为了清除任务队列中的任务。虽然都是清除任务队列中的任务,却有一些不同:TimerTask
类中的cancel
方法侧重的是将自身从任务队列中清除,其他任务不受影响,而Timer
类中的cancel
方法则是将任务队列中全部的任务清空。
purge方法就是用来释放内存引用的。purge方法会检查timer队列里标记为canceled的task,将对它的引用置为null。