AsyncTask原理总结

1个任务队列(SerialExecutor)

一个继承于Executor的静态内部类,因此是所有AsyncTask对象所共有的,作为任务调度,内部维护1个双向队列,通过同步锁修饰execute(Runnable),使得任务被一个一个添加进队列,所有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
30
31
32
33
34
35
36
37
38
39
40
private static class SerialExecutor implements Executor {
// SerialExecutor = 静态内部类
// 即 是所有实例化的AsyncTask对象公有的

// SerialExecutor 内部维持了1个双向队列;
// 容量根据元素数量调节
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;

// execute()被同步锁synchronized修饰
// 即 多个任务需1个个加到该队列中;然后 执行完队列头部的再执行下一个,以此类推
public synchronized void execute(final Runnable r) {
// 将实例化后的FutureTask类 的实例对象传入
// 即相当于:向队列中加入一个新的任务
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
// 若当前无任务执行,则去队列中取出1个执行
if (mActive == null) {
scheduleNext();
}
}

protected synchronized void scheduleNext() {
// 1. 取出队列头部任务
if ((mActive = mTasks.poll()) != null) {

// 2. 执行取出的队列头部任务
// 即 调用执行任务线程池类(THREAD_POOL_EXECUTOR)
THREAD_POOL_EXECUTOR.execute(mActive);

}
}
}

1个线程池(THREAD_POOL_EXECUTOR)

真正执行具体的线程任务,实际上是一个已经配置好的可执行并行任务的线程池。

内部Handler(InternalHandler)

用于在主线程更新线程执行的进度和结果。

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
private static class InternalHandler extends Handler {

// 构造函数
public InternalHandler() {
super(Looper.getMainLooper());
// 获取的是主线程的Looper()
// 故 AsyncTask的实例创建 & execute()必须在主线程使用
}

@Override
public void handleMessage(Message msg) {

AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;

switch (msg.what) {
// 若收到的消息 = MESSAGE_POST_RESULT
// 则通过finish()将结果通过Handler传递到主线程
case MESSAGE_POST_RESULT:
result.mTask.finish(result.mData[0]); ->>分析3
break;

// 若收到的消息 = MESSAGE_POST_PROGRESS
// 则回调onProgressUpdate()通知主线程更新进度的操作
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}

实现步骤

  1. 创建 AsyncTask 子类 & 根据需求实现核心方法:onPreExecute()doInBackground(arg)onPostExecute(result)onProgressUpdate(progress)onCancelled()
  2. 创建 AsyncTask 子类的实例对象(即 任务实例)
  3. 手动调用execute()executeOnExecutor(Executor)从而执行异步线程任务

注意

调用cancel(boolean)时并不会中止doInBackground(arg),需要在doInBackground(arg)函数中做判断处理,如isCancelled(),或捕获InterruptedException异常(当 cancel 传入参数为true时,会调用子线程的interrupt方法,可能会抛出InterruptedException异常)

0%