标签:
使用的优点:
l 简单,快捷
l 过程可控
使用的缺点:
l 在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来。
AsyncTask定义了三种泛型类型 Params,Progress和Result。(也是可以指定为空的,如 AsyncTask <Void, Void, Void>)
一个异步加载数据最少要重写以下这两个方法:
当然了,还可以重写以下这三个方法,但不是必须的:
使用AsyncTask类,以下是几条必须遵守的准则:
1、Task的实例必须在UI thread中创建;
2、execute方法必须在UI thread中调用;
3、不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
4、该task只能被执行一次,多次调用时将会出现异常;
执行的顺序是:onPreExecute(),doInBackground(),onProgressUpdate(),onPostExecute()。onCancelled()不一定会执行。
除了doInBackground是在子线程执行,其他的都是在UI线程执行的。
下面说下我们具体是怎么使用的:
第一步,创建一个异步任务的实例,并且执行,这里传入的参数对应的是AsyncTask的第一个参数:
MyTask mTask = new MyTask(); mTask.execute(url);第二步,建立一个异步任务的类,如下:
private class MyTask extends AsyncTask<String, Integer, String> {
//onPreExecute方法用于在执行后台任务前做一些UI操作
@Override
protected void onPreExecute() {
textView.setText("start loading...");
}
//doInBackground方法内部执行后台任务,不可在此方法内修改UI。这里传入的参数对应AsyncTask的第一个参数,即execute()函数传递过来的
@Override
protected String doInBackground(String... params) {
... //做一些耗时的动作
publishProgress(progresses); //progresses对应AsyncTask的第二个参数,同时也是要传给onProgressUpdate()的参数
...
return result; //返回值对应AsyncTask的第三个参数,同时也是要传给onPostExecute()的参数
}
//onProgressUpdate方法用于更新进度信息
@Override
protected void onProgressUpdate(Integer... progresses) {
textView.setText("loading..." + progresses[0] + "%");
}
//onPostExecute方法用于在执行完后台任务后更新UI,显示结果
@Override
protected void onPostExecute(String result) {
textView.setText(result);
}
//onCancelled方法用于在取消执行中的任务时更改UI
@Override
protected void onCancelled() {
textView.setText("cancelled");
}
}第三步,不是必须的,如果需要取消任务,可以调用:mTask.cancle(true);该函数一旦被调用就不会执行到onPostExecute()了,而是执行onCancelled()方法。
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return postResult(doInBackground(mParams));
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
...
}
};
}就是建立了WorkerRunnable和FutureTask两个实例,并把mWorker传递给了mFuture。public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}调用了executeOnExecutor,继续看下实现:public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
...
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}在这里我们看到了onPreExecute(),因此可以看出onPreExecute()是首先被执行的,然后调用了exec.execute(),从上面的代码中我们看到exec就是sDefaultExecutor,那么sDefaultExecutor是什么东东呢?我们看到了如下代码:public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); …… private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;也就是我们实际调用的是SerialExecutor的execute()方法,看下实现:
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
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);
}
}
}首先把任务放到mTasks这个集合里面;然后判断mActivie如果为空,就调用scheduleNext ()方法。void innerRun() {
if (!compareAndSetState(READY, RUNNING))
return;
runner = Thread.currentThread();
if (getState() == RUNNING) { // recheck after setting thread
V result;
try {
result = callable.call();
} catch (Throwable ex) {
setException(ex);
return;
}
set(result);
} else {
releaseShared(0); // cancel
}
}我们看到有调用callable.call(),而callable就是mWorker了,所以这里就执行到了下面的函数:public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return postResult(doInBackground(mParams));
}postResult(doInBackground(mParams))这一句就走到了doInBackground()方法了,并且将它的返回值传给了postResult,那我们看下postResult的具体实现吧!private Result postResult(Result result) {
Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}原来是使用了sHandler来发送消息,那我们再看下处理消息的地方: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[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}收到MESSAGE_POST_RESULT就执行finish(),收到MESSAGE_POST_PROGRESS就执行onProgressUpdate()。我们看下finish()的实现:private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}这里做了一个判断,根据任务是否被取消来调用不同的方法。protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}至此AsyncTask相关的流程就讲的差不多了,可以看到AsyncTask的任务执行是单线程的,关于AsyncTask的任务执行是单线程实现还是多线程实现是经历了一番变化的,较早的版本是单线程实现,从Android2.X开始,Google把它改为多线程实现,后来发现,多线程实现的话,会有很多需要保证线程安全的额外工作留给开发者,所以从Android3.0开始,又把默认实现改为单线程了。标签:
原文地址:http://blog.csdn.net/wdong_love_cl/article/details/51550353