关于AsyncTask的一些分析

源码地址
http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/android/os/AsyncTask.java

首先来看一下AsyncTask的构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
288    public AsyncTask() {
289 mWorker = new WorkerRunnable<Params, Result>() {
290 public Result call() throws Exception {
291 mTaskInvoked.set(true);
292
293 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
294 //noinspection unchecked
295 Result result = doInBackground(mParams);
296 Binder.flushPendingCommands();
297 return postResult(result);
298 }
299 };
300
301 mFuture = new FutureTask<Result>(mWorker) {
302 @Override
303 protected void done() {
304 try {
305 postResultIfNotInvoked(get());
306 } catch (InterruptedException e) {
307 android.util.Log.w(LOG_TAG, e);
308 } catch (ExecutionException e) {
309 throw new RuntimeException("An error occurred while executing doInBackground()",
310 e.getCause());
311 } catch (CancellationException e) {
312 postResultIfNotInvoked(null);
313 }
314 }
315 };
316 }

可以看到这个构造方法没有做特别多的工作,只是初始化了mWorker和mFuture.
再来看一下execute方法

1
2
3
550    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
551 return executeOnExecutor(sDefaultExecutor, params);
552 }

以及它调用的executeOnExecutor方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
588    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
589 Params... params) {
这里判断一下当前的状态,如果不是等候执行的状态,就抛出异常
590 if (mStatus != Status.PENDING) {
591 switch (mStatus) {
592 case RUNNING:
593 throw new IllegalStateException("Cannot execute task:"
594 + " the task is already running.");
595 case FINISHED:
596 throw new IllegalStateException("Cannot execute task:"
597 + " the task has already been executed "
598 + "(a task can be executed only once)");
599 }
600 }
601
602 mStatus = Status.RUNNING;
603
这里执行了Asynctask中的执行后台任务之前的准备方法
604 onPreExecute();
605
将参数传入woker
606 mWorker.mParams = params;
执行
607 exec.execute(mFuture);
608
609 return this;
610 }

调用execute的是sDefaultExecutor,来看一下这个sDefaultExecutor是什么

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
226    private static class SerialExecutor implements Executor {
227 final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
228 Runnable mActive;
229
230 public synchronized void execute(final Runnable r) {
231 mTasks.offer(new Runnable() {
232 public void run() {
233 try {
234 r.run();
235 } finally {
236 scheduleNext();
237 }
238 }
239 });
240 if (mActive == null) {
241 scheduleNext();
242 }
243 }
244
245 protected synchronized void scheduleNext() {
246 if ((mActive = mTasks.poll()) != null) {
247 THREAD_POOL_EXECUTOR.execute(mActive);
248 }
249 }
250 }

再看一下run方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}

跟一下callable的出处,发现这个它是在FutureTask的构造参数中被传入的,也就是那个mWorker,执行了它的call方法,再回头看看mWorker的初始化中如何重写的call方法

1
2
3
4
5
6
7
8
9
10
11
12
289        mWorker = new WorkerRunnable<Params, Result>() {
290 public Result call() throws Exception {
291 mTaskInvoked.set(true);
292
293 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
294 //noinspection unchecked
终于找到熟悉的doInBackground了
295 Result result = doInBackground(mParams);
296 Binder.flushPendingCommands();
297 return postResult(result);
298 }
299 };

再看看postResult的实现

1
2
3
4
5
6
7
325    private Result postResult(Result result) {
326 @SuppressWarnings("unchecked")
327 Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
328 new AsyncTaskResult<Result>(this, result));
329 message.sendToTarget();
330 return result;
331 }

以及getHandle返回的handler是一个InternalHandler,来看一下InternalHandler的源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
656    private static class InternalHandler extends Handler {
657 public InternalHandler() {
658 super(Looper.getMainLooper());
659 }
660
661 @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
662 @Override
663 public void handleMessage(Message msg) {
664 AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
665 switch (msg.what) {
可以看出这里进行了message消息的判断,如果收到了完成的消息,就执行完成相关的方法
如果是更新进度就执行更新进度相关的方法
666 case MESSAGE_POST_RESULT:
667 // There is only one result
668 result.mTask.finish(result.mData[0]);
669 break;
670 case MESSAGE_POST_PROGRESS:
671 result.mTask.onProgressUpdate(result.mData);
672 break;
673 }
674 }
675 }

再分别看一下finish

1
2
3
4
5
6
7
8
9
10
11
647    private void finish(Result result) {
如果任务被取消了就执行onCancelled方法
648 if (isCancelled()) {
649 onCancelled(result);
650 } else {
执行任务执行完毕后的方法并传入result
651 onPostExecute(result);
652 }
将当前任务状态改变为已结束
653 mStatus = Status.FINISHED;
654 }

至此,整个AsyncTask的任务已经完成。

关于一些其他的小问题

在SerialExecutor中一这样一段代码:

1
2
3
4
5
6
7
8
9
231            mTasks.offer(new Runnable() {
232 public void run() {
233 try {
234 r.run();
235 } finally {
236 scheduleNext();
237 }
238 }
239 });

前面只分析了r.run这个过程,而mTasks offer是怎么调用的并没有说,我们再来单独分析一下SerialExecutor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
226    private static class SerialExecutor implements Executor {
227 final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
228 Runnable mActive;
229
230 public synchronized void execute(final Runnable r) {
231 mTasks.offer(new Runnable() {
232 public void run() {
233 try {
234 r.run();
235 } finally {
236 scheduleNext();
237 }
238 }
239 });
240 if (mActive == null) {
241 scheduleNext();
242 }
243 }
244
245 protected synchronized void scheduleNext() {
246 if ((mActive = mTasks.poll()) != null) {
247 THREAD_POOL_EXECUTOR.execute(mActive);
248 }
249 }
250 }

mTasks是一个双端队列,看一下ArrayDeque的offer和poll方法分别做了什么事情

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 public boolean offer(E e) {
return offerLast(e);
}

public boolean offerLast(E e) {
addLast(e);
return true;
}

public void addLast(E e) {
if (e == null)
throw new NullPointerException("e == null");
elements[tail] = e;
if ( (tail = (tail + 1) & (elements.length - 1)) == head)
doubleCapacity();
}

offer是一个将runnable加入队列的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public E poll() {
return pollFirst();
}
返回队列头的数据
public E pollFirst() {
int h = head;
@SuppressWarnings("unchecked") E result = (E) elements[h];
// Element is null if deque empty
if (result == null)
return null;
elements[h] = null; // Must null out slot
head = (h + 1) & (elements.length - 1);
return result;
}

而在run的try catch块的finally中,执行了scheduleNext,则执行完一个任务后就会再执行下一个任务,模仿了单一线程池中的效果,也侧面印证了AsyncTask是串行的(Android3.0以下是并行)
如果想要在Android3.0以后并行执行,方法也很简单:

1
2
3
4
5
Executor exec = new ThreadPoolExecutor(15, 200, 10,  
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
new DownloadTask().executeOnExecutor(exec);

这一段摘自郭霖的博客http://blog.csdn.net/guolin_blog/article/details/11711405