AsyncTask源碼的理解
介紹
AsyncTask是Android中已經封裝好的,用於子線程操作的類。實現的主要方式仍然是Android中熟悉的Thread+Handler模式,
最終以模板的形式讓程序員使用。如果同一時間多次使用AsyncTask去執行任務,
默認情況下,這些子線程會按照FIFO的順序執行,不會併發執行。
執行流程
只是給出了大概的流程,細節的地方(比如onProgressUpdate()等)沒有提到,面面俱到的話會影響到對主要流程的把控。
相關代碼的註釋
public abstract class AsyncTask<Params, Progress, Result> {
private static final String LOG_TAG = "AsyncTask";
/*以下是爲了配置THREAD_POOL_EXECUTOR中的參數*/
//CPU的核數
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
//根據CPU的核數來動態的計算線程池的核心線程的個數
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
//根據CPU的核數來動態的計算線程池的最大線程的個數
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
//獲取隊列中任務的超時時間,當閾值時間內無法獲取線程,則會銷燬處理線程,前提是線程數量在corePoolSize 以上
執行隊列
private static final int KEEP_ALIVE = 1;
//線程工廠
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);
/*以上是爲了配置THREAD_POOL_EXECUTOR中的參數*/
//正真用來執行線程的的Executor,默認情況下與SERIAL_EXECUTOR配合使用
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
//默認情況下與THREAD_POOL_EXECUTOR配合使用,是線程成“串行”的方式來執行,也就是一個線程執行完畢後,纔會執行下一個
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
//用戶Handler發送消息的標識
//通知線程運行的結果
private static final int MESSAGE_POST_RESULT = 0x1;
//通知線程運行的進度
private static final int MESSAGE_POST_PROGRESS = 0x2;
//默認的Executor,是SERIAL_EXECUTOR,在多線程的情況下,是各個線程按FIFO串行
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
//用來通知UI線程的Handler
private static InternalHandler sHandler;
//與mFuture配合使用,doInBackground()在這裏執行
private final WorkerRunnable<Params, Result> mWorker;
//與mWorker配合使用,doInBackground()在這裏執行
private final FutureTask<Result> mFuture;
//標識狀態
private volatile Status mStatus = Status.PENDING;
//狀態,取消
private final AtomicBoolean mCancelled = new AtomicBoolean();
//狀態,執行
private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
//自定義execute()方法,通過隊列的方式來依次執行隊列中的子線程,這是保證AsyncTask中線程不會併發進行
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
//邏輯:1.往隊列裏添加子線程,沒有對mActive進行賦值
//2.mActive爲空,執行了scheduleNext()方法
//3.scheduleNext()中,從隊列中取第一個線程來執行
//4.執行完畢後,finally中,再次調用scheduleNext(),如果有新的子線程添加進來,繼續執行隊列中的頭一個子線程,直到隊列爲空
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) {
//這裏可以看出,真正執行子線程的Executor是THREAD_POOL_EXECUTOR
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
//用來表標識狀態
public enum Status {
//掛起
PENDING,
//運行
RUNNING,
//結束
FINISHED,
}
//獲取Handler
private static Handler getHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler();
}
return sHandler;
}
}
//如果不想串行,可以自定義Executor,不建議這樣做
/** @hide */
public static void setDefaultExecutor(Executor exec) {
sDefaultExecutor = exec;
}
//可以看出,在構造方法中,創建了mWorker和mFuture這兩個對象
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
//標識子線程調用了
mTaskInvoked.set(true);
//設置優先級,可以不考慮
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//doInBackground()調用的地方
//noinspection unchecked
Result result = doInBackground(mParams);
//系統的操作,不用管
Binder.flushPendingCommands();
//給Handler發送消息
return postResult(result);
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
//mWorker執行完畢後,會調用該方法
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);
}
}
};
}
//如果mWorker沒有執行,調用postResult()
private void postResultIfNotInvoked(Result result) {
//用來判斷mWorker是否調用了
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
//如果任務取消了,線程會中斷,可能沒有標識已經執行了(也就是沒有設置爲true),此處用來處理該中情況
postResult(result);
}
}
//給Handler發送消息,可以看出onPostExecute()是在UI線程中執行的
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
//獲取標識
public final Status getStatus() {
return mStatus;
}
//在子線程中執行耗時操作,必須重寫
@WorkerThread
protected abstract Result doInBackground(Params... params);
//在execute()中會看出是在主線程中執行的,並且最先調用,需要重寫
@MainThread
protected void onPreExecute() {
}
//在Handler中調用,說明是在UI線程中執行的,需要重寫
@SuppressWarnings({"UnusedDeclaration"})
@MainThread
protected void onPostExecute(Result result) {
}
//在Handler中調用,是UI線程,需要重寫
@SuppressWarnings({"UnusedDeclaration"})
@MainThread
protected void onProgressUpdate(Progress... values) {
}
//如果任務取消的話,會在finish()中調用該方法
@SuppressWarnings({"UnusedParameters"})
@MainThread
protected void onCancelled(Result result) {
onCancelled();
}
//如果任務取消的話,會在finish()中調用該方法
@MainThread
protected void onCancelled() {
}
//標識是否取消任務
public final boolean isCancelled() {
return mCancelled.get();
}
//設置任務是否取消
public final boolean cancel(boolean mayInterruptIfRunning) {
//更新標識
mCancelled.set(true);
//中斷任務,這裏可以看出使用Future可好處:可以對子線程進行控制
return mFuture.cancel(mayInterruptIfRunning);
}
//獲取任務執行的結果
public final Result get() throws InterruptedException, ExecutionException {
return mFuture.get();
}
//AsyncTask就是用此方法傳遞參數的
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
//execute正真執行的地方
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
//狀態不是“掛起”,就報錯,也就說明AsyncTask只能執行一次
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(),注意,此處仍然爲UI線程
onPreExecute();
//傳遞相應的參數
mWorker.mParams = params;
//mFuture和mWorker配合,先後執行了doInBackground()和onPostExecute()
exec.execute(mFuture);
//進一步說明:此處使用了“模板模式”,在使用過程中,我們只要根據需求,重寫onPreExecute(),doInBackground() ,onPostExecute()即可
return this;
}
//用線程池來執行Runnable,嗯,我想了半天,也就是可以省略一些配置,少些一些代碼而已,沒啥用
@MainThread
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}
//在doInBackground()中使用,用來通知子線程的進度
@WorkerThread
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
//任務結束時,通過Handler來調用
private void finish(Result result) {
//根據是否取消來執行相應的方法
if (isCancelled()) {
onCancelled(result);
} else {
//根據需求,重寫方法
onPostExecute(result);
}
//更新狀態
mStatus = Status.FINISHED;
}
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:
// There is only one result
//任務結束時執行
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
//給出任務執行中相應的進度
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
//用來封裝任務(子線程)數據
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
//用來封裝Handler的數據
@SuppressWarnings({"RawUseOfParameterizedType"})
private static class AsyncTaskResult<Data> {
final AsyncTask mTask;
final Data[] mData;
AsyncTaskResult(AsyncTask task, Data... data) {
mTask = task;
mData = data;
}
}
}
後記
AsyncTask中的成員變量大多是靜態的,如果在一個地方替換掉的話,再次使用的時候需要清除,AsyncTask中的一些設置已經不是默認的。
轉載請標明出處:http://blog.csdn.net/qq_26411333/article/details/51404760