Android的AsyncTask原始碼分析

yangxi_001發表於2013-11-18

一說到AsyncTask,大家就會說 ,他是系統提供給我的用於執行非同步任務的工具類。比Handler好用只需要重寫方法,每個Asynchronous物件只能執行1次。但是他必須要放在主執行緒裡建立。為什麼呢?這都是為什麼呢?我們就來對這些疑惑一探究竟:

         開啟這個類,我喜歡只有除去一些註釋只有250多行:

   二話不說,先看他的構造吧:

     public AsyncTask() {

        mWorker = new WorkerRunnable<Params, Result>() {

            public Result call() throws Exception {

                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

                return doInBackground(mParams);//呼叫了doInBackground

            }

        };//構建了一個mWorkà WorkerRunnable是具有prams引數的一個抽象類,實現了Callable介面。

        mFuture = new FutureTask<Result>(mWorker) {//mWorker建立了FutureTask

            @Override// FutureTask(Runnable runnable, V result)

//FutureTask通過一個Runnable/Callable構造,一旦執行完成通過get();返回一個Result

            protected void done() {

                Message message;

                Result result = null;

                try {

                    result = get();//獲得mWork返回的Result

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

              message=sHandler.obtainMessage(MESSAGE_POST_CANCEL,

new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));

                  // sHandler是自己的Handler:obtainMessage:通過what,obj獲得msg;

                                     //實際呼叫: Message.obtain(this, what, obj);得到1個MSg

                    message.sendToTarget();//target.send(msg)傳送了一個訊息給自覺封裝好的Handler

                    return;

                } catch (Throwable t) {

                    throw new RuntimeException("An error occured while executing "

                            + "doInBackground()", t);

                }

 

                message = sHandler.obtainMessage(MESSAGE_POST_RESULT,

                        new AsyncTaskResult<Result>(AsyncTask.this, result));

                message.sendToTarget();

            }

        };

    }

    這時呼叫了HandleMessage()方法,下面是那個Handler的具體程式碼:

         private static class InternalHandler extends Handler {

        @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})

        @Override//看到了吧,我們要重寫的幾個方法。他們現在都是空實現。

        public void handleMessage(Message msg) {

            AsyncTaskResult result = (AsyncTaskResult) msg.obj;//取得訊息裡的Result

            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;

                case MESSAGE_POST_CANCEL://當訊息時取消時的操作

                    result.mTask.onCancelled();

                    break;

            }

        }

    }

 

這裡涉及到一個AsyncTaskResult result和:

private static class AsyncTaskResult<Data> {//建立分派訊息時,將Result封裝為AsyncTaskResult

        final AsyncTask mTask;//封裝1個非同步任務,建立訊息時this

        final Data[] mData;//我們建立訊息時mData:為Result

        AsyncTaskResult(AsyncTask task, Data... data) {

            mTask = task;

            mData = data;

        }

    }

哪為什麼要在Ui執行緒例項化呢,:

         因為他的本質還是HandlerHandler物件與當前執行緒關聯,也就說,我們想通過非同步分離UI和後臺處理,當然要在Ui例項化。

         為什麼又只能執行1次呢:

我們看,通過程式碼的結構:我們要通過execute執行(為什麼?)來傳遞我們要執行的引數:

他內部定義了一個狀態並初始化為PENGDING

private volatile Status mStatus = Status.PENDING;

       public enum Status {PENDING, RUNNING, FINISHED, }

public final AsyncTask<Params, Progress, Result> execute(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;//只能在這裡修改1次,這就是執行1次的原因.

        onPreExecute();//如果定義了onPreExecute(),則執行,否則空實現;

        mWorker.mParams = params;//初始化mWorker的引數

        sExecutor.execute(mFuture);//這是執行FutureTask的方式。回到了我上面的講解。

        return this;

    }

         這裡也順便講一下Progress的更新吧:

                   protected final void publishProgress(Progress... values) {

        sHandler.obtainMessage(MESSAGE_POST_PROGRESS,

                new AsyncTaskResult<Progress>(this, values)).sendToTarget();

    }

這下,你是不是明白呢!


相關文章