AsyncTask 坑 AsyncTask对象多次执行
Posted zj510
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AsyncTask 坑 AsyncTask对象多次执行相关的知识,希望对你有一定的参考价值。
经常看到网上有这种面试题目:一个AsyncTask对象能不能被多次执行?
其实,想知道答案,最好的办法就是看文档说明,要是文档说不行那就是不行,行就是行。
如果想知道的更多,那就看代码呗。
AsyncTask的execute函数
excute是用来启动一个异步任务的API,先看看这个函数,
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params)
return executeOnExecutor(sDefaultExecutor, params);
下面的这个函数里面可以看到有个成员mStatus,代码很简单,如果mStatus不是PENDING,直接丢异常。
@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)");
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
看看状态枚举,很简单就只有3种状态,PENDING, RUNNING, FINISHED。
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,
看mStatus的变化流程:
1. AsyncTask对象创建的时候,初始化成PENDING.
private volatile Status mStatus = Status.PENDING;
2. execute()里面会判断,如果不是pending(无论是running,还是finished)都直接丢出异常。只有pending才能往下走。当是pending的时候,就直接设置成running。然后就发onPreExecute通知和执行任务。
3. 执行完后,无论成功还是失败,都设置成finished。
private void finish(Result result)
if (isCancelled())
onCancelled(result);
else
onPostExecute(result);
mStatus = Status.FINISHED;
从这些代码,其实就可以看出,一个AsyncTask对象被创建出来后,就只能执行一个异步任务。一旦开始执行了,无论在运行过程中,还是运行结束了,都不能在重复执行了。
FutureTask
之前也看到过,AsyncTask的构造函数里面,会创建一个mWorker和mFuture。mWorker会传给mFuture,mFuture里面的成员callable就是引用了mWorker对象。
然后FutureTask一次执行完后,就会调用下面的函数,很清楚callable被赋值为null了。
private void finishCompletion()
// assert state > COMPLETING;
for (WaitNode q; (q = waiters) != null;)
if (U.compareAndSwapObject(this, WAITERS, q, null))
for (;;)
Thread t = q.thread;
if (t != null)
q.thread = null;
LockSupport.unpark(t);
WaitNode next = q.next;
if (next == null)
break;
q.next = null; // unlink to help gc
q = next;
break;
done();
callable = null; // to reduce footprint
而mFuture和mWorker都是被声明称final的
private final WorkerRunnable<Params, Result> mWorker;
private final FutureTask<Result> mFuture;
那么当一个AsyncTask对象被创建出来后,mFuture和mWorker只能被初始化一次,而mFuture执行完一次任务后,就会调用finishCompletion,然后把callable赋值成0,也就是说就算后面再执行mFuture,因为callable被清0了,任务也不会再次执行。
从种种迹象表明,一个AsyncTask对象只能执行一次任务,是google刻意限制的。
至于为什么要设计成这样?
我想Google设计AsyncTask的初衷就是:这是个轻量级的类,用于执行简单的后台操作。
一个任务就是一个AsyncTask对象,如果想执行其他任务或者同个任务再执行一次,那就再创建一个AsyncTask对象呗。
以上是关于AsyncTask 坑 AsyncTask对象多次执行的主要内容,如果未能解决你的问题,请参考以下文章