從0開(kāi)始學(xué)安卓源碼分析--AsyncTask源碼

問(wèn)題:

  1. 為什么一個(gè)AsyncTask只能被執(zhí)行一次?
  2. 為什么AsyncTask是串行執(zhí)行的, 不能并行嗎?
  3. 為什么AsyncTask必須在UI線程中創(chuàng)建?

帶著問(wèn)題看源碼, 穩(wěn).

看一個(gè)源碼當(dāng)然從其構(gòu)造函數(shù)出發(fā).

public AsyncTask(@Nullable Looper callbackLooper) {
        // 這里是為什么需要在主線程創(chuàng)建的原因, 不然怎么去更新ui?
        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
            ? getMainHandler()
            : new Handler(callbackLooper);
        // WorkerRunnable實(shí)現(xiàn)callable接口并實(shí)現(xiàn)了它的call()方法
        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);
                }
            }
        };
    }

在這個(gè)構(gòu)造方法里可以看到doInBackground(mParams) 方法, 也就是我們繼承AsyncTask 復(fù)寫(xiě)的方法. 該方法返回了result結(jié)果, 最終在finally里調(diào)用postResult(result); 將結(jié)果通過(guò)handler傳遞進(jìn)行處理. 在handler的handleMessage中會(huì)調(diào)用AsyncTask的finish()方法.

private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }

這里就找到了 onPostExecute(result); 將結(jié)果通過(guò)onPostExecute回調(diào)到上層了.

FutureTask是一個(gè)可管理的任務(wù)類(lèi), 它實(shí)現(xiàn)了Runnable和Callable兩個(gè)接口, 稍微瞄一眼源碼可知其可以對(duì)Runnable和Callable進(jìn)行包裝.
這里將WorkerRunnable作為入?yún)鬟f給了FutureTask.
AsyncTask還并未開(kāi)始執(zhí)行, 真正執(zhí)行需要調(diào)用AsyncTask.execute(params);, 并將params傳遞進(jìn)去.

public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }

接著看executeOnExecutor(sDefaultExecutor, params);

這里需要看下AsyncTask的三個(gè)狀態(tài):

  • PENDING // 等待, 表示任務(wù)未執(zhí)行
  • RUNNING // 表示任務(wù)正在運(yùn)行
  • FINISHED // 表示任務(wù)已經(jīng)完成結(jié)束
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
            Params... params) {
        // 這里也是為什么一個(gè)AsyncTask只能執(zhí)行一次的原因
        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)");
            }
        }
        // 更改為運(yùn)行態(tài)
        mStatus = Status.RUNNING;
        // 執(zhí)行任務(wù)前調(diào)用onPreExecute()方法, 我們會(huì)在onPreExecute進(jìn)行一些不耗時(shí)初始化的操作
        onPreExecute();

        mWorker.mParams = params;
        // 這里開(kāi)始真正執(zhí)行task任務(wù)
        exec.execute(mFuture);

        return this;
    }

調(diào)用exec.execute(mFuture);真正執(zhí)行任務(wù)的exec是什么呢?
是傳遞進(jìn)來(lái)的sDefaultExecutor .

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

private static class SerialExecutor implements Executor {
        // ArrayDeque 先進(jìn)先出的雙端隊(duì)列
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
        Runnable mActive;

        public synchronized void execute(final Runnable r) {
            // 先將任務(wù)都存入隊(duì)列里
            // 當(dāng)前沒(méi)有執(zhí)行的任務(wù)則從隊(duì)列中取出一個(gè)用THREAD_POOL_EXECUTOR執(zhí)行.
            // 當(dāng)前有執(zhí)行的任務(wù)則是在任務(wù)完成后的finally里取出一個(gè)執(zhí)行
            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是一個(gè)靜態(tài)的串行執(zhí)行器, 也就是如果都調(diào)用AsyncTask.execute(params);方法, 那么一個(gè)進(jìn)程內(nèi)所有AsyncTask都是由sDefaultExecutor 串行執(zhí)行的. 這樣保證一個(gè)時(shí)間只有一個(gè)任務(wù)執(zhí)行.
如果需要并行執(zhí)行任務(wù)則需要調(diào)用executeOnExecutor(Executor exec,Params... params)

另外注意再看看THREAD_POOL_EXECUTOR

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

線程池用到了一個(gè)容量128的阻塞隊(duì)列.

到這里我們繼承AsyncTask需要復(fù)寫(xiě)的方法,就都已經(jīng)在流程中出現(xiàn)了

  • onPreExecute()
  • doInBackground(params)
  • onPostExecute(result)

還有另外一個(gè)onProgressUpdate(progress) 在哪兒呢?
搜索一下源碼.

protected final void publishProgress(Progress... values) {
        if (!isCancelled()) {
            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                    new AsyncTaskResult<Progress>(this, values)).sendToTarget();
        }
    }

可以在doInBackground()中調(diào)用publishProgress()方法來(lái)進(jìn)行進(jìn)度的更新. 通過(guò)handler來(lái)將更新進(jìn)度發(fā)布到UI線程并回調(diào)onProgressUpdate(progress)方法

AsyncTask的源碼到這里已經(jīng)分析完了, 總的來(lái)說(shuō)難度不大. 最后AsyncTask可能會(huì)導(dǎo)致內(nèi)存泄漏, 記得適時(shí)的調(diào)用AsyncTask的cancel()方法

理解記憶關(guān)鍵詞:
handler、FutureTask(Runnable)、SerialExecutor線程池、主線程初始化

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 架空小言,純屬虛構(gòu) chapter31 留家(2) 紹珩在酒店外廊的臺(tái)階上等了不到十分鐘,匡家的車(chē)子便到了。他見(jiàn)匡...
    春衫冷閱讀 6,004評(píng)論 3 3
  • 2017年3月,教育部公布最新的中國(guó)公民出國(guó)留學(xué)和外國(guó)公民留學(xué)中國(guó)情況。單從總量來(lái)看,和2016年相比,兩項(xiàng)數(shù)據(jù)都...
    劈柴捌哥閱讀 543評(píng)論 0 1
  • 《旋風(fēng)女隊(duì)》這部電影主要講述了從小就擁有足球夢(mèng)的女主人公吳小麗,因?yàn)樯砀卟粔虻木壒?,無(wú)法做職業(yè)球員后,一心想把足...
    左佳璐閱讀 1,134評(píng)論 0 1

友情鏈接更多精彩內(nèi)容