IllegalStateException解析

本文解析了Android开发中AsyncTask与Timer出现IllegalStateException的原因及解决方法。针对AsyncTask只能执行一次的问题,提供了合理的代码重构建议;对于Timer取消后无法再次调度的情况,也给出了相应的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值