AsyncTask源碼分析

開始分析

從最常調用的 execute(Params... params) 方法開始

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(),將任務params封裝進mWorker,再以mFuture作為參數,調用exec的execute()方法。

ok..mWorker是啥,mFuture是什么,參數sDefaultExecutor又是什么?
別著急,一個一個地看

mWorker

private final WorkerRunnable<Params, Result> mWorker;
    
public AsyncTask() {
    mWorker = new WorkerRunnable<Params, Result>() {
        public Result call() throws Exception {
            mTaskInvoked.set(true);

            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            //noinspection unchecked
            return postResult(doInBackground(mParams));
        }
    };
    //...
}
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
    Params[] mParams;
}    

WorkerRunnable類型的mWorker封裝了Params,并且實現了Callable接口。在call()方法中回調doInBackground()方法,并將結果作為參數調用postResult()方法。

postResult()其實是通過handle調用finish()方法,而finish()方法則回調我們實現的onCancelled()或onPostExecute()方法。

mFuture

private final FutureTask<Result> mFuture;

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

public class FutureTask<V> implements RunnableFuture<V> {
    //...
    public void run() {
        //...
        V result;
        result = c.call();
        //...
        }
    }
    //...
}

public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}

很簡單,mFuture其實是一個Runable對象,它的run()方法調用mWorker的call()方法。

SERIAL_EXECUTOR、sDefaultExecutor和THREAD_POOL_EXECUTOR

public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

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

它們都是靜態的。

THREAD_POOL_EXECUTOR是一個線程池對象,用于處理AsyncTask的異步任務

sDefaultExecutor是一個Executor對象,內部管理一個名為mTasks的隊列,這個對象有兩個方法,分別是scheduleNext()和實現接口的execute(Runnable r)方法。

  • scheduleNext()方法是從mTasks隊頭取出一個Runnable任務賦值給mActive,并交由THREAD_POOL_EXECUTOR線程池處理。

  • execute(Runnable r)作了以下幾件事:

    1. 把傳入Runnable型的參數進一步封裝,執行完任務后調用scheduleNext()
    2. 將封裝后的Runnable對象放入mTasks隊尾
    3. 如果當前mActive為空,則調用scheduleNext()

幾個問題

考慮首次調用sDefaultExecutor的execute()方法會出現什么情況?

一個任務還沒執行完,再次調用sDefaultExecutor的execute()方法呢?

執行完隊列的任務后,再次調用execute()方法呢?

至此,AsyncTask的基本實現原理已經了解,也弄清了幾個常見方法是何時被回調的了,那么對AsyncTask的源碼分析就可以告一段落了。

分析要點

  1. 帶著問題。常用回調是何時進行的,例如onPreExecute()、doInBackground()、onPostExecute()等。
  2. 不要過多糾結細節。比如FutureTask這個類這么多方法都有什么用,我們的目的是分析AsyncTask實現原理,只要關心它是Runable類型的,以及它在run()方法中調用mWorker的call()方法就行了。
  3. 注意分析順序,比如從我們調用的execute(Params... params)方法開始,查看它的實現。
  4. 弄清楚其中關鍵語句所涉及到的對象是怎么作用的。如:
    1. mWorker封裝任務Params,在call()方法中回調doInBackground()和onPostExecute();
    2. exec是類的對象(靜態)sDefaultExecutor,它負責管理所有任務的執行順序;
    3. mFuture封裝mWorker,并作為Runnable對象被exec管理。
  5. 多使用快捷鍵進行代碼跳轉,比如點擊鼠標中鍵進入方法體;用鼠標大拇指兩個健控制前進和后退。
  6. 還有什么姿勢,希望大家也能參與總結。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 使用AsyncTask的一般步驟是: 定義一個類繼承自AsyncTask,實現抽象方法 new 一個AsyncTa...
    yk_looper閱讀 396評論 0 2
  • 轉載請注明出處:http://www.lxweimin.com/p/531657db36f4 上一篇主要說了下Asy...
    朋永閱讀 283評論 0 0
  • AsyncTask源碼分析:AsyncTask是一種輕量級的異步任務類,它是一個泛型抽象類,提供了Params, ...
    dawen92閱讀 200評論 0 0
  • 我有個同學,每天晚上看書看到很晚,上課永遠做前排中央,每次復習都到凌晨。 每次期末考試都是專業前幾。 可是她總是說...
    漁阿樵閱讀 270評論 0 0
  • 夕陽斜斜地照進屋里,像往常一樣,她慵懶地蜷在躺椅上,陽光灑在她臉上,映出歲月的痕跡,她輕撫著那張模糊不清的照片...
    詣西閱讀 348評論 0 2