作者:周伟 (werii.zhou@gmail.com)
http://blog.163.com/android_zhouwei/blog/static/1712422672010818105241892/
一说到AsyncTask,大家就会说 ,他是系统提供给我的用于执行异步任务的工具类。比Handler好用只需要重写方法,每个Asynchronous对象只能执行1次。但是他必须要放在主线程里创建。为什么呢?这都是为什么呢?我们就来对这些疑惑一探究竟:
打开这个类,我喜欢只有除去一些注释只有250多行:
二话不说,先看他的构造吧:
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return doInBackground(mParams);//调用了doInBackground
}
};//构建了一个mWorkà WorkerRunnable是具有prams参数的一个抽象类,实现了Callable接口。
mFuture = new FutureTask<Result>(mWorker) {//用mWorker创建了FutureTask
@Override//FutureTask
(Runnable runnable, V result)
//FutureTask通过一个Runnable/Callable构造,一旦运行完成通过get();返回一个Result
protected void done() {
Message message;
Result result = null;
try {
result = get();//获得mWork返回的Result
} 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<Result>(AsyncTask.this, (Result[]) null));
// sHandler是自己的Handler:obtainMessage:通过what,obj获得msg;
//实际调用: Message.obtain(this, what, obj);得到1个MSg
message.sendToTarget();//target.send(msg)发送了一个消息给自觉封装好的Handler
return;
} catch (Throwable t) {
throw new RuntimeException("An error occured while executing "
+ "doInBackground()", t);
}
message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(AsyncTask.this, result));
message.sendToTarget();
}
};
}
这时调用了HandleMessage()方法,下面是那个Handler的具体代码:
private static class InternalHandler extends Handler {
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override//看到了吧,我们要重写的几个方法。他们现在都是空实现。
public void handleMessage(Message msg) {
AsyncTaskResult result = (AsyncTaskResult) msg.obj;//取得消息里的Result
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;
case MESSAGE_POST_CANCEL://当消息时取消时的操作
result.mTask.onCancelled();
break;
}
}
}
这里涉及到一个AsyncTaskResult result和:
private static class AsyncTaskResult<Data> {//创建分派消息时,将Result封装为AsyncTaskResult
final AsyncTask mTask;//封装1个异步任务,创建消息时this
final Data[] mData;//我们创建消息时mData:为Result
AsyncTaskResult(AsyncTask task, Data... data) {
mTask = task;
mData = data;
}
}
哪为什么要在Ui线程实例化呢,:
因为他的本质还是Handler,Handler对象与当前线程关联,也就说,我们想通过异步分离UI和后台处理,当然要在Ui实例化。
为什么又只能执行1次呢:
我们看,通过代码的结构:我们要通过execute执行(为什么?)来传递我们要执行的参数:
他内部定义了一个状态并初始化为PENGDING:
private volatile Status mStatus = Status.PENDING;
public enum Status {PENDING, RUNNING, FINISHED, }
public final AsyncTask<Params, Progress, Result> execute(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;//只能在这里修改1次,这就是执行1次的原因.
onPreExecute();//如果定义了onPreExecute(),则执行,否则空实现;
mWorker.mParams = params;//初始化mWorker的参数
sExecutor.execute(mFuture);//这是执行FutureTask的方式。回到了我上面的讲解。
return this;
}
这里也顺便讲一下Progress的更新吧:
protected final void publishProgress(Progress... values) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
这下,你是不是明白呢!