AsyncTask源碼的理解

AsyncTask源碼的理解

介紹

AsyncTask是Android中已經封裝好的,用於子線程操作的類。實現的主要方式仍然是Android中熟悉的Thread+Handler模式,
最終以模板的形式讓程序員使用。如果同一時間多次使用AsyncTask去執行任務,
默認情況下,這些子線程會按照FIFO的順序執行,不會併發執行。

執行流程

只是給出了大概的流程,細節的地方(比如onProgressUpdate()等)沒有提到,面面俱到的話會影響到對主要流程的把控。

Created with Raphaël 2.1.0創建AsyncTask對象創建mWorker和mFuture,並將兩者關聯調用execute()方法,傳入相應的參數判斷是否“掛起”狀態?修改狀態爲“運行”,並在主線程中調用onPreExecute();把參數傳入mWorker,在子線程mWorker中執行doInBackground()子線程運行是否正常?doInBackground()運行完畢後,使用sHandler通知主線程調用finish()finishi()中,判斷是否取消調用onCancelled(),由調用者自行處理結束調用onPostExecute(),由調用者自行處理mFutrue中postResultIfNotInvoked()中的postResult()會調用拋出異常yesnoyesnoyesno

相關代碼的註釋

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章