尊重原创,转发请注明出处。
做安卓开发,平常我的项目里很经常会用到异步任务,特别是一些获取网络数据的地方,我们都知道这种耗时操作要新起线程去获取,但是获取到数据后我们不能在非UI线程里操作控件,这个时候我们通常的做法是利用Handler进行跨线程传递信息。而AsyncTask实际上就是封装了这么一个新起Thread做耗时操作+利用Handler跨进程通信实现异步任务的这么一个过程,使我们用起来十分方便。
接下来我们就从源码的角度来解析一下AsyncTask里面是如何实现这一过程的:
先来看看AsyncTask里面的几个方法以及他们的意义:
1.onPreExecute():这个是在异步请求之前调用的
2.doInBackground():在这里面实现异步请求
3.onPostExecute():处理异步请求回来的结果
4.onProgressUpdate():请求的进度
5.execute():开始执行这个异步任务
接下来来分析一下他的实现流程:
首先AsyncTask拥有线程池,每一个异步任务都放入到这个线程池里,来看看AsyncTask的构造函数的源码:
public AsyncTask() {
//这里面封装调用了doInBackGround(),即实现去异步请求的操作
mWorker = new WorkerRunnable() {
public Result call() throws Exception {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return doInBackground(mParams);
}
};
//而这里面封装当异步请求回来收到结果要给UI线程发送的几种消息(只是封装这么一个过程,并还没有在这里面执行这个Task)
mFuture = new FutureTask(mWorker) {
@Override
protected void done() {
Message message;//消息
Result result = null;
try {
result = get();
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
new AsyncTaskResult(AsyncTask.this, (Result[]) null));
message.sendToTarget();//取消任务,则发送取消任务的消息
return;
} catch (Throwable t) {
throw new RuntimeException("An error occured while executing "
+ "doInBackground()", t);
}
//没有报错或异常的话则把获取到的结果发送给UI线程
message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult(AsyncTask.this, result));//完成任务,发送MESSAGE_POST_RESULT消息并传递result对象
message.sendToTarget();
}
};
}
我们知道当我们调用AsnycTask的execute()方法的时候将会触发这个异步任务执行,接下来看一下execute()方法里做了些什么:
public final AsyncTask execute(Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
//如果是任务正在执行中
case RUNNING:
throw newIllegalStateException("Cannot execute task:"
+ " the taskis already running.");
//如果任务已经执行完成
case FINISHED:
throw newIllegalStateException("Cannot execute task:"
+ " the taskhas already been executed "
+ "(a task canbe executed only once)");
}
}
//如果任务还未执行
mStatus = Status.RUNNING;
onPreExecute();//这里在开启异步请求之前调这个方法
mWorker.mParams = params;
sExecutor.execute(mFuture);//把任务提交到线程池,开始执行
return this;
}
那么UI线程里肯定要有个Handler来接收这个消息,并且调用onPostExecute(),这个Handler就是InternalHandler,他是定义在UI线程里的,接下来先看一下他的源码:
private static class InternalHandler extends Handler {
@SuppressWarnings({"unchecked","RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult result =(AsyncTaskResult) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT://异步任务执行成功,获取到请求结果
result.mTask.finish(result.mData[]);//finish()里面会调用onPostExecute()
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);//进度更新的消息,调用onProgressUpdate()来根据返回的进去更新UI
break;
case MESSAGE_POST_CANCEL://取消任务的消息,则取消任务
result.mTask.onCancelled();
break;
}
}
}
通过注释可以很明了的看明白了,我们看到执行异步任务成功获取到返回结果的话,这里是调了一个finish(),那么finish()里面做了些什么呢,其实finish()里调用了
onPostExecute()。
相信通过以上对源码的解析,应该对AsyncTask的实现原理以及他里面的那几个方法有了更加深刻的理解,接下来总结一下:
其实AsyncTask的实现原理概括就是:新开线程执行异步请求+Handler发送结果到UI线程
AsyncTask的封装给我们使用异步任务的时候带来很多便捷,也更加的直观,使用起来十分容易。
关于AsyncTask的实现原理就先讲到这了,有什么地方讲的有误或者不全面,希望指正,不剩感激!