AsyncTask是一个抽象泛型类,它有三个参数,分别是Params,Progress和Result,其中Params为参数类型,Progress为后台执行任务的进度,Result为返回的结果的类型。如果不需要某个参数,可以将其设置为Void类型。

AsyncTask中有四个核心的方法:

onPreExecute:在主线程中执行,一般在任务执行前做准备工作,比如对UI做一些标记。doInBackground(Params…params):在线程池中执行。在onPreExecute方法执行后运行,用来执行较为耗时的操作。在执行过程中可以调用publishProgress(Progress…values)来更新进度信息。

onProgressUpdate(Progress…values):在主线程中执行。当调用publishProgress(Progress…values)时,此方法会将进度更新到UI组件上。

onPostExecute(Result result):在主线程中执行。当后台任务执行完成后,它会被执行。doInBackground方法得到的结果就是返回的result的值。此方法一般做任务执行后的收尾工作,比如更新UI和数据。

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
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;

private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);

public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};

private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);

/**
* An {@link Executor} that can be used to execute tasks in parallel.
*/
public static final Executor THREAD_POOL_EXECUTOR;

static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}

这里的corePoolSize获取的是Java虚拟机的可用的处理器数量来计算的

maximumPoolSize也是根据这个来计算的

keepAliveTime的时间是30s

阻塞队列采用的是LinkedBlockingQueue,容量为128

ThreadFactory给线程起了”AsyncTask#”这样格式的名字

这样就完成了线程池的构造。

接着看一下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
public AsyncTask(@Nullable Looper callbackLooper) {
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);

mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};

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 occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}

这里强调一下,AsyncTask的execute方法一定要在主线程中调用,因为这里的handler一定要是getMainHandler,具体的原因下面会讲。此外创建了一个WorkRunnable对象mWorker,这个WorkRunnable实现了Calable接口,并实现了call方法,并且在该方法中调用了doInBackground方法类处理任务并得到结果,最终还通过postResult将结果传递了出去。这里的FutureTask是一个可管理的异步任务,它实现了Runnable和Future这两个接口。所以,它可以包装Runnable和Callable,并且提供给Executor执行,在这里我们将WorkerRunnable作为参数传递给了FutureTask。接下来我们看一下execute方法:

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
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方法,然后将参数传给mWorker。前面我们已经说过WokrerRunnable作为参数传递给了FutureTask,因此,参数被封装到了FutureTask中。接下来我们看一下exec这个对象:

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
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);
}
}
}

从上面的代码可以看出该对象表示的是一个串行的线程池,当调用execute方法时,会将futureTask加入到mTask中。且当任务执行完或者当前没有活动是都会执行scheduleNext方法,会从mTasks中取出FutureTask任务并交由THREAD_POOL_EXECUTOR处理。执行的时候因为传进来的是由WorkerRunnable作为参数的FutureTask,所以会执行WorkerRunnable的call方法,在call方法中会将结果通过postResult方法传递出去:

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

可以看到,上面说的使用getMainHandler和这里的getHandler是一样的,在这里创建了Message,并通过Handler发送了该消息:

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 Handler getMainHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}

private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}

@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;
}
}
}

这里自定义了一个Handler并处理了它的处理方式,可以看到上面发送的消息会调用finish方法:

1
2
3
4
5
6
7
8
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}

这里判断了是否被取消,如果被取消了,则调用onCancelled方法,否则调用onPostExecute方法。

本文地址: http://www.yppcat.top/2019/04/12/AsyncTask原理分析/