AsyncTask
源码看似比较独立和简单,分析一下
AsyncTask
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// 这里调用后台运行
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
// 发送结果
return postResult(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);
}
}
};
}
构造函数,分别构造了一个WorkerRunnable
和一个FutureTask
WorkerRunnable
就是任务,里面保存了Params
,在执行结束后返回Result
FutureTask
包装了一下任务,实际调度的是它,它会运行那个WorkerRunnable
,得到返回结果在done()
中处理
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
线程相关接口和类
// 可被执行的命令,不返回结果
public interface Runnable {
public void run();
}
// 一个任务,能够返回结果,可能抛出异常
public interface Callable<V> {
V call() throws Exception;
}
// Future代表了一个异步任务的结果
// 有方法检查任务是否完成、等待完成、获得任务结果
// 结果只能当任务完成时通过get()获得,必要的话会阻塞直到就绪
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
// 一个可运行的Future
// run()的成功执行导致Future的完成,并且允许访问其结果
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
// 一个可取消的异步任务
// 可以用来包裹Runnable或Callable
// 因为实现了Runnable,所以可以提交给一个Executor处理
// 可以开始和结束任务,查看任务结果
public class FutureTask<V> implements RunnableFuture<V> {
public FutureTask(Callable<V> callable) {
......
}
public FutureTask(Runnable runnable, V result) {
......
}
......
}
工作流
通过execute()
执行,返回任务的引用,调用者可以保持引用
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread
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;
}
线程池执行任务,FutureTask.run()
public void run() {
if (state != NEW || !U.compareAndSwapObject(this, RUNNER, 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 = null;
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
protected void set(V v) {
if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
outcome = v;
U.putOrderedInt(this, STATE, NORMAL);
finishCompletion();
}
}
private void finishCompletion() {
for (WaitNode q; (q = waiters) != null;) {
if (U.compareAndSwapObject(this, WAITERS, q, null)) {
for (;;) {
Thread t = q.thread;
if (t != null) {
q.thread = null;
LockSupport.unpark(t);
}
WaitNode next = q.next;
if (next == null)
break;
q.next = null;
q = next;
}
break;
}
}
// 这个done()就是匿名类中重写的方法,表示完成后的处理
done();
callable = null;
}
完成后会调用这个,发消息从后台执行前台动作
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
那么一定有消息处理器
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
private void finish(Result result) {
if (isCancelled()) {
// 取消
onCancelled(result);
} else {
// 执行结束
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
线程注解
如果你的方法只能在指定的线程类型中被调用,那么你就可以使用以下4个注解来标注它:
@UiThread
@MainThread
@WorkerThread
@BinderThread
如果一个类中的所有方法都有相同的线程需求,那么你可以注解类本身。比如android.view.View
,就被用@UiThread
标注。
关于线程注解使用的一个很好的例子就是AsyncTask
:
如果你在重写的doInBackground()
方法里尝试调用onProgressUpdate()
方法或者View
的任何方法,就会马上把它标记为一个错误
@UiThread
还是@MainThread
?
在进程里只有一个主线程。这个就是@MainThread
。同时这个线程也是一个@UiThread
。比如Activity
的主要窗口就运行在这个线程上。然而它也有能力为应用创建其他线程。这很少见,一般具备这样功能的都是系统进程。通常是把和生命周期有关的用@MainThread
标注,和View
层级结构相关的用@UiThread
标注。但是由于@MainThread
本质上是一个@UiThread
,而大部分情况下@UiThread
又是一个@MainThread
,所以你能在一个可以调用@MainThread
方法的地方也能调用@UiThread
方法,反之亦然。
Executor
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
// 这个执行器是串行的
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
// 这个执行器是并行的
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
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);
}
}
}
// 这个方法可以指定使用的执行器
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params);
最初的版本,AsyncTask
在单个后台线程上顺序执行
从API4(1.6)
开始,变成了允许多个任务并行进行的线程池
从API11(3.0)
开始,任务在一个单一线程执行以避免并行操作引起的错误
如果你需要并行执行,可以使用executeOnExecutor()
,传入THREAD_POOL_EXECUTOR
总结
AsyncTask
是一个简单的在工作线程处理任务的方式,通过线程池调度任务(默认或者指定),后台任务的执行结果通过Handler
机制发消息给UI线程
更新界面