介绍
AsyncTask是一种轻量级的异步任务类,它可以在线程池执行后台任务,然后把执行的进度和结果传递给主线程并在主线程中更新UI。
AsyncTask
public class DownLoadAsyncTask extends AsyncTask {
private String taskName;
public DownLoadAsyncTask(String taskName) {
this.taskName = taskName;
}
/**
* 主线程
* 做任务开始前准备工作
*/
@Override
protected void onPreExecute() {
super.onPreExecute();
}
/**
* 子线程
* 执行后台耗时任务
* @param strings
* @return
*/
@Override
protected String doInBackground(String... strings) {
try {
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return taskName;
}
/**
* 主线程
* 任务执行进度的回调
* 当在doInBackground中调用publishProgress方法时,该方法会被回调
* @param values
*/
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
/**
* 主线程
* 任务执行结束后回调
* @param s
*/
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Log.e("m1ku", s + "finished at " + df.format(new Date()));
}
}
new DownLoadAsyncTask("task#1").execute("www.baidu.com");
使用AsyncTask时,只需要先实例化并调用其execute方法,以上复写的几个方法机会依次调用完成任务的执行。
源码分析
AsyncTask构造方法
public AsyncTask() {
this((Looper) null);
}
public AsyncTask(@Nullable Looper callbackLooper) {
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
mWorker = new WorkerRunnable() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
mFuture = new FutureTask(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
首先获取到主线程的Handler对象,然后初始化一个WorkerRunnable对象mWorker,该对象实现了Callable接口,mParams参数是这个对象的成员变量。使用mWorker构造了FutureTask对象mFuture,FutureTask实现了RunnableFuture接口,RunnableFuture又继承了Runnable和Future接口,所以FutureTask是一个可取消的并且可以被线程池执行的异步任务计算类。
execute方法
@MainThread
public final AsyncTask execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread
public final AsyncTask 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;
}
首先判断当前不在等待状态,如果状态是RUNNING正在运行时抛出异常,如果状态是FINISHED已经结束时也抛出异常即一个AsyncTask只能执行一次。将当前task状态置为RUNNING,并调用onPreExecute方法,将传入的参数赋值给前面初始化过的mWorker对象,最后调用sDefaultExecutor的execute方法传入mFuture。sDefaultExecutor定义如下
private static class SerialExecutor implements Executor {
final ArrayDeque mTasks = new ArrayDeque();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
在execute方法中,将Runnable对象添加到mTasks队列中,并在该Runnable的run方法中调用了mFuture的run。
由于当前mActive为空,调用scheduleNext方法,该方法中首先为mActive赋值,如果不为空则使用THREAD_POOL_EXECUTOR线程池执行mActive。mActive为mTasks的第一个元素,它的run方法被调用,mFuture的run方法被调用,执行完毕后再finally中又调用了scheduleNext方法继续执行下一个Runnable即执行mFuture任务对象。mFuture的run方法如下
public void run() {
if (state != NEW ||
!U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
return;
try {
Callable c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
其中调用了c.call()方法,即传入的Callable对象mWorker的call方法
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
调用doInBackground方法,而在doInBackground中我们会手动调用publishProgress方法
@WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult
使用Handler发送进度更新消息,将当前线程从线程池中切换到了主线程中
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult> result = (AsyncTaskResult>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
在handleMessage中调用了onProgressUpdate方法对外公布了任务执行的进度。最后在finally块中调用了postResult方法
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult(this, result));
message.sendToTarget();
return result;
}
这里同样是将结果通过handler发送到了主线程中,如上在handleMessage中调用finish方法
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
判断当前任务已经取消时回调取消方法,否则回调onPostExecute方法对外公布任务执行的结果,最后将任务状态置为FINISHED。
通过分析AsyncTask的源码,可以得出几点结论
- 一个AsyncTask只能执行一次。
- 由于sHandler是一个静态成员在类加载时进行初始化,所以AsyncTask必须要在主线程中加载。
- AsyncTask中有两个线程池,SERIAL_EXECUTOR负责任务的排队,THREAD_POOL_EXECUTOR才负责任务的执行。
- AsyncTask中任务默认是串行执行的。