Android源碼解析-Asynctask

android源碼分析-AsyncTask

我們一般創(chuàng)建一個AsyncTask的任務(wù)代碼如下:

AsyncTask<String , String , String> task = new AsyncTask<String, String, String>() {
    @Override
        protected void onPreExecute() {
            //UI線程,線程開始前執(zhí)行,一般用于初始化操作
                super.onPreExecute();
            }
        @Override
        protected String doInBackground(String... params) {
            //子線程后臺線程執(zhí)行操作
                return null;
            }
        @Override
        protected void onProgressUpdate(String... values) {
            //UI線程,進度更新,通過在doInBackground方法中調(diào)用publishProgress傳遞過來更新進度
                super.onProgressUpdate(values);
            }
        @Override
        protected void onPostExecute(String s) {
            //UI線程,后臺操作執(zhí)行完畢執(zhí)行
                super.onPostExecute(s);
            }
    };
task.execute();

下面開始分析源碼:

流程先看AsyncTask的構(gòu)造方法:

public AsyncTask() {
    mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                    mTaskInvoked.set(true);
                        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                        //noinspection unchecked
                        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);
                            }
                    }
            };
    }

1.代碼開始看可能有些難懂.其實說明一下就好很多了,WorkerRunnable是自定義的一個抽象類.里邊先定義了進程的線程優(yōu)先級(跟我們要講的暫時沒啥關(guān)系),又實現(xiàn)了doInBackground()方法,這就發(fā)現(xiàn)了doInBackground就是我們demo上new AsyncTask()必須重寫的方法,AsyncTask中doInBackground()方法有注解@WorkerThread,說明他在工作線程.
2.然后return了postResult(result);,而且在new FutureTask中也調(diào)用了postResultIfNotInvoked(get());,而這個方法最后也是調(diào)用了postResult(result),所以來繼續(xù)跟蹤這個方法:

private Result postResult(Result result) {
    @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,new AsyncTaskResult<Result>(this, result));
                message.sendToTarget();
        return result;
    }

看到了熟悉的老朋友Message,然后有個方法message.sendToTarget();,這個是Message的方法,之前http://m.itdecent.cn/p/1e5f34f6635e文檔中有說過.
然后繼續(xù)看getHandler(),這個不是Handler的方法,我們可以追蹤這個方法"

private static Handler getHandler() {
    synchronized (AsyncTask.class) {
            if (sHandler == null) {
                    sHandler = new InternalHandler();
                    }
                return sHandler;
            }
    }

看到了sHandler = new InternalHandler();說明重點代碼就在InternalHandler()類:

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

根據(jù)消息類型判斷是否結(jié)束如果結(jié)束就走finish方法.
這里我們又看到了另一個熟悉的名字onProgressUpdate(),用來更新進度用的實現(xiàn)方法.如果沒結(jié)束就走這個分支.
看一下上邊說的finish方法:

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

這個就很好理解了,取消就調(diào)用取消的回調(diào),結(jié)束就調(diào)用結(jié)束的回調(diào).

我們還有個回調(diào)方法沒找到,我們看一下:

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

這個調(diào)用應(yīng)該是在doInBackground()方法中.通知onProgressUpdate()刷新進度.
看到了這里也是發(fā)出了一個Message.就應(yīng)該在InternalHandler中的刷新進度的分支接受到消息.

下面看execute()方法:

通過跟蹤發(fā)現(xiàn)調(diào)用了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;
    }

這里有個回調(diào)方法onPreExecute()就是在執(zhí)行doInBackground()前在主線程執(zhí)行的方法.

然后把參數(shù)賦給了mWorker.mParams,然后執(zhí)行了exec.execute(mFuture);,這句就是讓線程執(zhí)行任務(wù)的關(guān)鍵代碼.
這個類點不進去了,但是我們找到了另外一個execute(runnable)的方法,跟蹤看一下有個sDefaultExecutor.execute(runnable);,
然后看一下sDefaultExecutor是什么鬼.繼續(xù)找,找到了SERIAL_EXECUTOR,看看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);
                    }
            }
    }

這里有兩個類executescheduleNext()方法,作用是把任務(wù)反倒隊列中執(zhí)行.
mTasks.offer方法是把任務(wù)放到隊列末尾,THREAD_POOL_EXECUTOR.execute(mActive)應(yīng)該是從頭部取任務(wù)執(zhí)行.
我覺得這的代碼應(yīng)該是新建ArrayDeque<Runnable> 線程隊列,然后加了同步鎖,執(zhí)行了run開啟線程,在結(jié)束的時候從線程池取出線程.
這樣整個異步任務(wù)就執(zhí)行完了.

總結(jié)

通過構(gòu)造方法,實現(xiàn)了mWorker和mFuture(線程池類),先實現(xiàn)了doInBackground()告訴程序開啟線程做什么,然后調(diào)用了postResult(),這個方法建立了Handler和Message系列,并且在Handler中接收結(jié)束和更新進度的msg.(現(xiàn)在有個問題mWorker中return的postResult()時機問題,為什么要在這里調(diào)用結(jié)束的方法?可能是mFuture里邊做的,畢竟最后mWorker也是mFuture的參數(shù),這里也請看到的大神們指導(dǎo)一下).
execute()方法在調(diào)用exec.execute(mFuture);前實現(xiàn)了onPreExecute()調(diào)用了線程開啟的回調(diào)方法.接著新建ArrayDeque<Runnable> 線程隊列,把mFuture任務(wù)添加到隊尾,線程池從隊列頭取出任務(wù)執(zhí)行.(可見Asynctask的任務(wù)是逐個完成的),這樣異步任務(wù)就實現(xiàn)了.

有什么不對的地方,請大神們不吝賜教!

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

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

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