IllegalStateException解析

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);

注:以上是个人开发中遇到的心得,如有不当,还望不吝赐教。

发布了23 篇原创文章 · 获赞 70 · 访问量 11万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览