在Android中,为我们提供了两种异步操作机制,一种是Handler另一种就是AsyncTask了。
如何使用AsyncTask?
自定义类继承AsyncTask,必须重写doInBackground方法,然后可以根据需求重写onPreExecute、onPostExecute、onProgressUpdate、onCancelled等方法。
然后调用execute方法去执行。
接下来我们就从execute这个方法,去看看AsyncTask 是怎样的一个流程。
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
我们可以看到在execute方法中调用了executeOnExecutor方法,传入了sDefaultExecutor和params,sDefaultExecutor是什么呢?
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
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);
}
}
}
通过这里我们就知道了sDefaultExecutor也就相当于SerialExecutor 的实例对象,
接下来看看executeOnExecutor方法做了些什么事情。
@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;
}
这个方法首先判断了当前的执行状态,意思也就是每个AsyncTask的execute方法只能调用一次。然后调用了一下onPreExecute方法,这个方法是一个空实现的方法是,目的就是我们在使用AsyncTask重写这个方法,去做一些开始前的准备工作。然后把params赋值给mWorker的mParams 。mWorker是一个实现了Callable接口的类。然后就调用了sDefaultExecutor的execute方法,传入了mFuture,mFuture是FutureTask对象,方便用于之后得到处理的结果。回到上面看看execute方法,添加一个Runnable到ArrayDeque的最后,ArrayDeque是一个串行的队列。
然后调用了scheduleNext方法,这个方法调用了THREAD_POOL_EXECUTOR的execute方法,把ArrayDeque的第一个线程对象去处理。到这里我们也知道了,AsyncTask是一个串行的机制。
//cpu数量
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
//核心线程的数量 2-4
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);
//线程池对象
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;
}
THREAD_POOL_EXECUTOR其实就是一个线程池对象,执行的线程也就是我们的mFuture里面的mWorker这个线程。要执行一个线程肯定要执行run方法,看看它的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 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);
}
}
先是调用call方法得到结果,在call里面就有我们doInBackground方法,完成后调用postResult方法返回结果。
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);
}
}
};
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
mFuture初始化实在构造方法中,当工作线程执行完毕,就会调用done方法,通过postResultIfNotInvoked判断是否将消息返回了,如果没有返回将消息返回。
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}
下面看看内部的Handler,在构造方法中的初始化
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
使用当前的现成的Looper对象构造Handler,如果传入的Looper对象为为空,或者是主线程的Looper会使用内部的InternalHandler 对象,如果其他线程的Handler需自己实现handleMessage方法。
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;
}
}
}
里面MESSAGE_POST_RESULT类型就是消息处理完成返回的结果,只能调用一次,而MESSAGE_POST_PROGRESS是当前的进度,通过publishProgress方法调用。
@WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
到这里AsyncTask的基本流程已经完成。
总结:
在构造方法中,初始化Handler对象,工作线程(Callable),和FutureTask(用于获取线程的返回结果)。通过调用execute方法,将任务加入一个串行队列中进行排队,然后交给线程池去处理任务,得到返回结果通过Handler完成线程的调度。
网友评论