http://blog.csdn.net/linmiansheng/article/details/20315823
Android在框架层提供了异步任务类,AysncTask,用于执行后台任务,并将执行结果更新到UI线程。为什么要用异步任务呢?这是因为如果某个任务太耗时间的话,会阻塞UI主线程,而我们知道UI线程如果阻塞5秒的话,就会发生ANR(Application No Response)错误 ,就算没有发生,主界面上看起来也会卡卡的,这显然用户体验就不太好了。
而AsyncTask类则在不影响UI线程的情况下,另起子线程去做那些耗时比较久的任务,比如我们在TodoList中去读取图片这种情况,然后将处理后的结果再更新到UI线程,从而达到更好的用户体验。
下面是AsyncTask类的定义:
- public abstract class AsyncTask<Params, Progress, Result> {
- private static final String LOG_TAG = "AsyncTask";
- ...
从上面的代码可以看出,AsyncTask是一个抽象类,所以在使用AsyncTask的时候,我们要继承它,实现一个子类,并实现其中一个方法,如下:
- class LoadImageTask extends AsyncTask<String, Void, ImageView>{
- @Override
- protected ImageView doInBackground(String... params) {
- String photoImagePath = params[0];
- Bitmap bitmap = BitmapReader.readBigBitmapFromFile(photoImagePath,REQ_WIDTH);
- ImageView imageView = Helper.createImageViewFromBitmap(DetailActivity.this, bitmap);
- return imageView;
- }
- protected void onPostExecute(ImageView result) {
- imageViews.add(result);
- refreshGallery();
- }
- }
对照 AsyncTask的三个参数,Params, Progress和Result,是泛型参数。
1)Params :参数,比如例子中定义的String类型,指向一个Image的路径,这是传给AysncTask的doInBackground方法。
2)Progress:这是在执行过程中会用到的一个参数,一般在显示进度的时候会用到,在例子中不会用到,所以可以在这里指定为Void。
3)Result:这是执行的结果对象,会作为onPostExecute方法的参数,在UI线程中处理。
由上面的例子也可以看到,一般我们实现的这个子类,要实现其中的两个方法
1)doInBackground:这个方法,其实是在另外一个线程中执行的。
2)onPostExecute:而这个方法却已经回到UI线程中来执行,所以可以在这里将上一个方法中执行所得的结果在这里更新到UI线程中。
那么这里面的机制是怎么样的呢,我们就来深入地看一下,也学习一下吧。
首先我们来看一下在Activity中,我们是怎么样来使用我们这个AsyncTask的吧,代码如下:
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data){
- if (requestCode == REQUEST_FOR_CAMERA) {
- if(resultCode == RESULT_OK){
- isPhotoTaken = true;
- photoFileNames.add(tempPhotoFileName);
- }
- } else if (requestCode == REQUEST_FOR_GALLERY) {
- if(resultCode == RESULT_OK){
- isPhotoTaken = true;
- ContentResolver resolver = getContentResolver();
- Uri uri = data.getData();
- tempPhotoFileName = Helper.getImagePath(resolver, uri);
- photoFileNames.add(tempPhotoFileName);
- }
- }
- new LoadImageTask().execute(tempPhotoFileName);//调用其execute方法
- }
在TodoList的小demo中,在相机或者图库返回来图片的路径之后,我们就会调用AsynctTask的execute方法了,那么这里就是入口了。
进入AsyncTask类中,找到execute方法,如下:
- public final AsyncTask<Params, Progress, Result> execute(Params... params) {
- return executeOnExecutor(sDefaultExecutor, params);
- }
- 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方法做一些处理工作,这个方法其实我们也可以在子类中自己实现,如果有什么需要处理的话,一般不用。
然后我们发现,我们传进来的参数params会被传给mWorker,然后会有一个executor来执行execute的方法,并且执行的参数是一个mFuture对象。那么这两个东西是什么呢?
接着看如下代码:
- public AsyncTask() {
- mWorker = new WorkerRunnable<Params, Result>() {
- public Result call() throws Exception {
- mTaskInvoked.set(true);
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- //noinspection unchecked
- return postResult(doInBackground(mParams));
- }
- };
- 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 occured while executing doInBackground()",
- e.getCause());
- } catch (CancellationException e) {
- postResultIfNotInvoked(null);
- }
- }
- };
- }
mWorker是一个WorkerRunnable对象,而实际上WorkerRunnable是AsyncTask的一个抽象内部类,实现了Callable接口,如下:
- private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
- Params[] mParams;
- }
而在上面的赋值过程,通过匿名类实现了WorkerRunnable,并其call方法中将线程优先级调整为后台线程,然后会执行 doInBackground方法,不过现在还没执行,咱们再看看FutureTask对象,下面是它的构造函数:
- public FutureTask(Callable<V> callable) {
- if (callable == null)
- throw new NullPointerException();
- sync = new Sync(callable);
- }
而FutureTask是Java多线程模型的一部分,其间接地实现了Runnable(线程属性)接口和Future(异步任务)接口,而在上面的executeOnExecutor方法中,正是将mWorker(实现了Callable接口)对象传给它了,并被其封装到成员变量sync中,这样它们就共同表示了一个异步任务,到这里,一个异步任务也就创建完成了。
从上面executeOnExecutor的方法,也可以看到,真正执行execute是一个Executor,而在AsyncTask中,其实是SerialExecutor,我们看看其构造函数:
- 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();//在新线程中调用了我们上面传进来的FutureTask的run方法
- } finally {
- scheduleNext();
- }
- }
- });
- if (mActive == null) {
- scheduleNext();
- }
- }
- protected synchronized void scheduleNext() {
- if ((mActive = mTasks.poll()) != null) {
- THREAD_POOL_EXECUTOR.execute(mActive);
- }
- }
- }
从上面,我们可以看到execute方法的参数就是一个Runnable,其实也就是FutrueTask了,在这里,它会被封装到一个新的线程中作为一个任务添加到mTasks队列中,至于下面如何在THREAD_POOL_EXECUTOR中去执行mTasks我们就不再深入下去了,我们就来看看FutureTask的run方法,如下:
- public void run() {
- sync.innerRun();
- }
我们发现,它调用的是sync.innerRun(),那么Sync的innerRun方法又干了什么呢?
- 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
- }
- }
但同时我们发现,其执行完之后,是作为一个参数传递给postResult的,继续看下去:
- private Result postResult(Result result) {
- @SuppressWarnings("unchecked")
- Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
- new AsyncTaskResult<Result>(this, result));
- message.sendToTarget();
- return result;
- }
- private static final InternalHandler sHandler = new InternalHandler();
- 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:
- // 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,则会调用mTask的finish方法,然后就结束了,而如果是MESSAGE_POST_PROGRESS,则会调用 onProgressUpdate方法,那么,很显然这个mTask应该就是我们定久的AsyncTask了吧。我们看看AsyncTaskResult是什么先,
- @SuppressWarnings({"RawUseOfParameterizedType"})
- private static class AsyncTaskResult<Data> {
- final AsyncTask mTask;
- final Data[] mData;
- AsyncTaskResult(AsyncTask task, Data... data) {
- mTask = task;
- mData = data;
- }
- }
- private void finish(Result result) {
- if (isCancelled()) {
- onCancelled(result);
- } else {
- onPostExecute(result);
- }
- mStatus = Status.FINISHED;
- }
嗯,关于AsyncTask的基本原理到这里也就结束了。