AsyncTask源码分析

关于AsyncTask的用法可以参看前面一篇博客《AsyncTask实现断点续传》,本文只解析AsyncTask的源代码。
 
AsyncTask.execute方法:
1     public final AsyncTask<Params, Progress, Result> execute(Params... params) {
2         return executeOnExecutor(sDefaultExecutor, params);
3     }
execute方法里面直接调用了executeOnexecute方法。
 
AsyncTask.executeOnexecute方法:
 1     public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
 2             Params... params) {
 3         if (mStatus != Status.PENDING) {
 4             switch (mStatus) {
 5                 case RUNNING:
 6                     throw new IllegalStateException("Cannot execute task:"
 7                             + " the task is already running.");
 8                 case FINISHED:
 9                     throw new IllegalStateException("Cannot execute task:"
10                             + " the task has already been executed "
11                             + "(a task can be executed only once)");
12             }
13         }
14         mStatus = Status.RUNNING;
15         onPreExecute();
16         mWorker.mParams = params;
17         exec.execute(mFuture);
18         return this;
19     }
        3-13行是检测AsyncTask的状态,如果状态不为PENDING,则会抛异常,这也是为什么一个AsyncTask只能被执行一次的原因。14行将状态改为RUNNING,表示该任务正在运行。然后调用AsyncTask的onPreExecute()方法。
        由下面代码可以看出,AsyncTask有三种状态:PENDING(未运行)、RUNNING(正在运行)、FINISHED(已运行完毕)。
 1     public enum Status {
 2         /**
 3          * Indicates that the task has not been executed yet.
 4          */
 5         PENDING,
 6         /**
 7          * Indicates that the task is running.
 8          */
 9         RUNNING,
10         /**
11          * Indicates that {@link AsyncTask#onPostExecute} has finished.
12          */
13         FINISHED,
14     }
 
        FutureTask代码:
 1 public class FutureTask<V> implements RunnableFuture<V> {
 2     ......
 3     //构造方法传入一个Callable对象
 4     public FutureTask(Callable<V> callable) {
 5         if (callable == null)
 6             throw new NullPointerException();
 7         this.callable = callable;
 8         this.state = NEW;       // ensure visibility of callable
 9     }
10     public void run() {
11         if (state != NEW ||
12             !UNSAFE.compareAndSwapObject(this, runnerOffset,
13                                          null, Thread.currentThread()))
14             return;
15         try {
16             Callable<V> c = callable;
17             if (c != null && state == NEW) {
18                 V result;
19                 boolean ran;
20                 try {
21                     result = c.call();//这里调用了callable.call()方法
22                     ran = true;
23                 } catch (Throwable ex) {
24                     result = null;
25                     ran = false;
26                     setException(ex);
27                 }
28                 if (ran)
29                     set(result);
30             }
31         } finally {
32             // runner must be non-null until state is settled to
33             // prevent concurrent calls to run()
34             runner = null;
35             // state must be re-read after nulling runner to prevent
36             // leaked interrupts
37             int s = state;
38             if (s >= INTERRUPTING)
39                 handlePossibleCancellationInterrupt(s);
40         }
41     }
42     ......
43 }

 

        AsyncTask构造方法:
 1 public abstract class AsyncTask<Params, Progress, Result> {
 2     ......
 3     /**
 4      * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
 5      */
 6     public AsyncTask() {
 7         mWorker = new WorkerRunnable<Params, Result>() {
 8             public Result call() throws Exception {
 9                 mTaskInvoked.set(true);
10                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
11                 //noinspection unchecked
12                 return postResult(doInBackground(mParams));
13             }
14         };
15         //创建FutureTask对象的时候传入了mWorker作为Callable
16         mFuture = new FutureTask<Result>(mWorker) {
17             @Override
18             protected void done() {
19                 try {
20                     postResultIfNotInvoked(get());
21                 } catch (InterruptedException e) {
22                     android.util.Log.w(LOG_TAG, e);
23                 } catch (ExecutionException e) {
24                     throw new RuntimeException("An error occured while executing doInBackground()",
25                             e.getCause());
26                 } catch (CancellationException e) {
27                     postResultIfNotInvoked(null);
28                 }
29             }
30         };
31     }
32     ......
33 }

 

        由FutureTask源码我们可以看出,run()方法里面调用了c.call(),而AsyncTask 中创建FutureTask的时候传入了mWorker,所以FutureTask.run()方法里面c.call()调用的是mWorker对象的call()方法,而AsyncTask里mWorker重写了call方法,即上面8-14行,所以c.call()会执行到mWorker.call()方法来。call方法里面11行将线程的优先级设置为后台线程,这样当多个线程并发后很多无关紧要的线程分配的CPU时间将会减少,有利于主线程的处理。
        接下来11行执行了doInBackground(mParams)方法,通常我们会重写该方法来实现业务逻辑操作。然后执行postResult方法,并且将结果返回给FutureTask(因为是FutureTask.run方法调用的此call方法,所以需要返回结果到FutureTask.run方法)。这里我们先看看postResult:
1     private Result postResult(Result result) {
2         @SuppressWarnings("unchecked")
3         Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
4                 new AsyncTaskResult<Result>(this, result));
5         message.sendToTarget();
6         return result;
7     }

        这里的sHandler是InternalHandler对象。
 1     private static class InternalHandler extends Handler {
 2         @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
 3         @Override
 4         public void handleMessage(Message msg) {
 5             AsyncTaskResult result = (AsyncTaskResult) msg.obj;
 6             switch (msg.what) {
 7                 case MESSAGE_POST_RESULT:
 8                     // There is only one result
 9                     result.mTask.finish(result.mData[0]);
10                     break;
11                 case MESSAGE_POST_PROGRESS:
12                     result.mTask.onProgressUpdate(result.mData);
13                     break;
14             }
15         }
16     }

        由第9行代码可知最终会执行AsyncTask的finish方法,代码如下:
1     private void finish(Result result) {
2         if (isCancelled()) {
3             onCancelled(result);
4         } else {
5             onPostExecute(result);
6         }
7         mStatus = Status.FINISHED;
8     }

        finish的作用是如果task被取消了就执行onCancelled方法,如果没有被取消而是正常执行完毕,则执行onPostExecute方法(这也是为什么task被调用了cancel方法,不会执行onPostExecute的原因)。最后将task的状态标记为FINISHED。
        
        上面说到mWorker.call会将执行结果返回给FutureTask.run()方法并且继续往下执行,我们再次看看FutureTask.run方法(20-30行):
 1 boolean ran;
 2 try {
 3      result = c.call();
 4      ran = true;
 5 } catch (Throwable ex) {
 6      result = null;
 7      ran = false;
 8      setException(ex);
 9 }
10 if (ran)
11      set(result);

        由上面代码可以看到,执行完c.call后,会执行set(result)方法。
1     protected void set(V v) {
2         if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
3             outcome = v;
4             UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
5             finishCompletion();
6         }
7     }

        最终会执行finishCompletion()方法。
 1     private void finishCompletion() {
 2         // assert state > COMPLETING;
 3         for (WaitNode q; (q = waiters) != null;) {
 4             if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
 5                 for (;;) {
 6                     Thread t = q.thread;
 7                     if (t != null) {
 8                         q.thread = null;
 9                         LockSupport.unpark(t);
10                     }
11                     WaitNode next = q.next;
12                     if (next == null)
13                         break;
14                     q.next = null; // unlink to help gc
15                     q = next;
16                 }
17                 break;
18             }
19         }
20         done();
21         callable = null;        // to reduce footprint
22     }

        看到21行代码,会执行FutureTask的done()方法,而这个方法在AsyncTask构造函数中初始化FutureTask对象的时候被重写了。
 1     mFuture = new FutureTask<Result>(mWorker) {
 2             @Override
 3             protected void done() {
 4                 try {
 5                     postResultIfNotInvoked(get());
 6                 } catch (InterruptedException e) {
 7                     android.util.Log.w(LOG_TAG, e);
 8                 } catch (ExecutionException e) {
 9                     throw new RuntimeException("An error occured while executing doInBackground()",
10                             e.getCause());
11                 } catch (CancellationException e) {
12                     postResultIfNotInvoked(null);
13                 }
14             }
15         };
        这里主要是验证postResult是否被调用了,如果没有被调用着调用postResult函数,因为前面mWorker.call方法里面调用过了,所以这里不错操作。
 
        顺便提一下,在AsyncTask的doInBackground方法中如果需要更新UI的话,则调用AsyncTask的publishProgress方法即可:
1     protected final void publishProgress(Progress... values) {
2         if (!isCancelled()) {
3             sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
4                     new AsyncTaskResult<Progress>(this, values)).sendToTarget();
5         }
6     }

        publishProgress方法最终也会通过sHandler来调用AsyncTask的onProgressUpdate方法,一般我们如果需要获取进度的话都需要重写AsyncTask的onProgressUpdate。
 
        好了,AsyncTask的源码也分析完了。再次总结一下Asynctask使用的注意事项:

   1.异步任务的实例必须在UI线程中创建。

  2.execute(Params... params)方法必须在UI线程中调用。

  3.不要手动调用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)这几个方法。

  4.不能在doInBackground(Params... params)中更改UI组件的信息。

  5.一个任务实例只能执行一次,如果执行第二次将会抛出异常。

 
posted @ 2015-10-11 00:19  残剑_  阅读(1456)  评论(0编辑  收藏  举报