1. AsyncTask IllegalStateException
最初的写法如下
if (asyncTask == null) {
asyncTask = new MyAsyncTask();
} else {
asyncTask.cancel(true);
}
asyncTask.execute();
则在测试中偶现:
java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
遂分析原因
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
... ...
}
public enum Status {
/**
* Indicates that the task has not been executed yet.
*/
PENDING,
/**
* Indicates that the task is running.
*/
RUNNING,
/**
* Indicates that {@link AsyncTask#onPostExecute} has finished.
*/
FINISHED,
}
以上表明,一个AsyncTask对象只能执行一次,如果再次执行,则会抛出以上异常。
在第一次执行asyncTask.execute()时,
private volatile Status mStatus = Status.PENDING;
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) {
... ...
mStatus = Status.RUNNING;
... ...
}
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
则Status的变化为:PENDING→RUNNING→FINISHED
故,第二次调用asyncTask.execute(),其Status已是FINISHED,所以会抛出以上异常。
遂更改写法,如下
if (asyncTask != null) {
asyncTask.cancel(true);
}
asyncTask = new MyAsyncTask();
asyncTask.execute();
如果task存在,则取消之前的,将asyncTask重新索引到一个新的AsyncTask,并去执行。
2. Timer IllegalStateException
mTimer.cancel();
mTimer.schedule(task, delay);
当Timer取消后,再次调用,则会抛出异常:java.lang.IllegalStateException: Timer was canceled
分析原因
public void schedule(TimerTask task, long delay) {
if (delay < 0) {
throw new IllegalArgumentException("delay < 0: " + delay);
}
scheduleImpl(task, delay, -1, false);
}
private void scheduleImpl(TimerTask task, long delay, long period, boolean fixed) {
synchronized (impl) {
if (impl.cancelled) {
throw new IllegalStateException("Timer was canceled");
}
... ...
}
}
private static final class TimerImpl extends Thread {
... ...
/**
* True if the method cancel() of the Timer was called or the !!!stop()
* method was invoked
*/
private boolean cancelled;
... ...
}
遂更改写法,如下
if (mTimer != null) {
mTimer.cancel();
}
mTimer = new Timer();
mTimer.schedule(task, delay);
注:以上是个人开发中遇到的心得,如有不当,还望不吝赐教。