AsyncTask这个类用的比较多,平时做项目时,一般用在文件下载这一块多比较多。其使用起来还算方便,实现根本的原理还是Thread + Handler。这篇文章就来谈谈AsyncTask的基本使用以及其原理实现,同时说说其和Handler的关系。
1、AsyncTask的基本使用
使用AsyncTask都得实现一个AsyncTask的子类,并在其中重载AsyncTask的一些方法(publishProgress不需要重载,也不能重载,这里放在一起讲),下面就来对这些方法做一些介绍。
protected void onPreExecute()
这个方法主要是在异步执行前去执行一些初始化的工作,因为onPreExecute方法实际上是执行在主线程,所以可以在其中执行一些界面操作。
protected abstract Result doInBackground(Params... params)
这个放是一个异步方法了,也就是说它不是在主线程中执行,故不能再其中执行界面操作,但是由于其是异步方法所以一般在方法体内执行一些耗时操作,不如文件下载等。
protected final void publishProgress(Progress... values)
这个方法用来在doInBackground方法的中抛出进度数据,并通过传递Handler消息,将数据传到后面要讲的onProgressUpdate方法中。
protected void onProgressUpdate(Progress... values)
上面说了,这个方法接收来自publishProgress方法传递过来的数据,并且由于通过Handler机制接收的数据,所以onProgressUpdate这个方法实际是在主线程中执行的,所以能在其中进行界面操作,一般我们在这个方法体中操作进度条。
protected void onPostExecute(Result result)
doInBackground方法执行完毕后会调用改方法,并且由于doInBackground也是通过Handler机制给onPostExcute传递数据,所以在这个方法中也可以操作界面。
protected void onCancelled()
protected void onCancelled(Result result)
这两个方法没啥好说的,也就是取消doInBackground的执行,进而阻断整个异步过程。
另外我们看看AsyncTask类的声明
public abstract class AsyncTask<Params, Progress, Result>
对比这里的泛型参数和以上几个方法的参数,我们很容易知道,
Params是doInBackground接收的参数类型
Progress是publishProgress以及onProgressUpdate两个方法接收的参数类型
Result是onPostExecute以及onCancelled接收的参数类型
2、AsyncTask工作原理说明
第一小节说明了AsyncTask子类需要重载(或者可以重载)的一些方法,当定义好子类后便可通过子类的实例执行execute方法便可以启动任务运行。
execute方法会执行到下面方法中
@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;
}
这里是一个主线程,并在其中执行了onPreExecute方法,这就是我们前面说的onPreExecute执行在主线程中的原因。接着会通过一个线程管理器来执行mFuture,这个mFuture是一个Runable子类实例。
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(result);
}
};
mFuture = new FutureTask<Result>(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);
}
}
};
而exec.execute(mFuture)方法会执行到FutureTask.run方法,在执行run方法中有以下代码
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
这个代码中的c.call()方法调用上面mWorker中的call方法,并在其中执行doInBackground并返回result,然后run方法中接着调动set(result)将result值赋给FutureTask.outcome对象。
run方法最终会执行会mFuture的done方法中来,再看done方法里的postResultIfNotInvoked(get())方法这里有个get()方法获取FutureTask.outcome对象(也就是doInBackground方法返回的result值),然后postResultIfNotInvoked方法会执行到以下postResult方法
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
到这里我们看到使用了Handler机制来传递消息了,那么接受消息的Handler呢就是下面这位大哥了
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@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;
}
}
}
它会根据传过来的MESSAGE_POST_RESULT去执行finish方法,我们再跟一下
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
当没有执行cancel操作时,finish方法会执行onPostExecute方法并获取doInBackground传递过来的值。
以上代码我们说清楚了onPreExecute、doInBackground、onPostExecute这几个方法。
接着我们看看当调用publishProgress方法时,执行如下代码
@WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
我们看到这里还是使用了Handler机制,并传MESSAGE_POST_PROGRESS消息,对比上面的Handler,我们知道Handler接受到消息后会执行onProgressUpdate方法。
这里便讲清了publishProgress方法同onProgressUpdate方法之间的关系。
最后,当在执行过程中进行cancel操作时,会在执行上面的finish方法是执行到onCancelled方法中去而不是执行onPostExecute方法。
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
这样就说清了onCancelled方法。
3、参考文献
1、详[解Android中AsyncTask的使用](http://blog.csdn.net/liuhe688/article/details/6532519)