Asynctask原理

AsyncTask 異步任務,主要包含兩個關鍵類:

InternalHandler:消息處理器, 用於處理線程之間消息.

ThreadPoolExecutor:線程池, 用於處理耗時任務



1、onPreExecute(): 在UI線程裏面調用,它在這個task執行後會立即調用。我們在這個方法裏面通常是用於建立一個任務,比如顯示一個等待對話框來通知用戶。
2、doInBackground(Params...):這個方法從名字就可以看出,它是運行在後臺線程的,在這個方法裏面,去做耗時的事情,比如下載訪問網絡,操作文件等。
這這個方法裏面,我們可以調用publishProgress(Progress...)來調用當前任務的進度,調用了這個方法後,對應的onProgressUpdate(Progress...)方法會被調用,
這個方法是運行在UI線程的。
3、onProgressUpdate(Progress...):運行在UI線程,在調用publishProgress()方法之後。這個方法用來在UI上顯示任何形式的進度,比如你可以顯示一個等待對話框,
也可以顯示一個文本形式的log,還可以顯示toast對話框。
4、onPostExecute(Result):當task結束後調用,它運行在UI線程。
5、取消一個task,我們可以在任何時候調用cancel(Boolean)來取消一個任務,當調用了cancel()方法後,onCancelled(Object)方法就會被調用,
onPostExecute(Object)方法不會被調用,在doInBackground(Object[])方法中,我們可以用isCancelled()方法來檢查任務是否取消。
6、幾點規則:
AsyncTask實例必須在UI線程中創建   
execute(Params...)方法必須在UI線程中調用。
不用手動調用onPreExecute(), onPostExecute(), doInBackground(), onProgressUpdate()方法。
一個任務只能被執行一次

------------------------------------

# AsyncTask原理


new AsyncTask<String, String, String>() {

// 2. 運行在主線程中, 做一些準備操作.
public void onPreExecute() {


}


// 3. 運行在子線程中, 做一些耗時的任務.
public String doInBackground(String... params) {
return null;
}


// 4. 運行主線程中, result就是doInBackground方法返回的值. 做一些收尾操作.
public void onPostExecute(String result) {


}
}.execute(String... params); // 1. 開始執行異步任務.


> #### AsyncTask的execute的方法, 代碼如下: 


public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        ...


        mStatus = Status.RUNNING;


// 調用用戶的實現方法, 讓用戶做一些準備操作. 運行在主線程中.
        onPreExecute();


// 把mWorker中的mParams賦值爲用戶傳遞進來的參數.
        mWorker.mParams = params;
// 使用線程池, 執行任務. 這時進入到子線程中.
        sExecutor.execute(mFuture);


        return this;
    }


> #### 查看mWorker的初始化過程, 代碼如下:


// AsyncTask構造函數在一開始使用異步任務時, 已經調用.
public AsyncTask() {
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                ...
            }
        };


// 1. 把mWorker對象傳遞給了FutureTask的構造函數
        mFuture = new FutureTask<Result>(mWorker) {
            @Override
            protected void done() {
                ...
            }
        };
    }


// FutureTask類中接收的是Callable的類型, 其實WorkerRunnable類型實現了Callable的類型.
    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
// 2. 把callable(mWorker)傳遞給了Sync的構造函數.
        sync = new Sync(callable);
    }


    Sync(Callable<V> callable) {
  // 3. 把接收過來的callable(mWorker)對象賦值給Sync類中的成員變量callable
// 總結: Sync類中的成員變量callable就是AsyncTask中的mWorker對象.
        this.callable = callable;
    }


> #### mFuture對象中的run方法如下:


public void run() {
// 1. 調用了innerRun方法.
        sync.innerRun();
    }


    void innerRun() {
        if (!compareAndSetState(READY, RUNNING))
            return;


        runner = Thread.currentThread();
        if (getState() == RUNNING) { // recheck after setting thread
            V result;
            try {
// 2. 調用了callable(mWorker)的call方法. 獲取一個返回結果.
                result = callable.call();
            } catch (Throwable ex) {
                setException(ex);
                return;
            }
// 4. 把結果傳遞給set方法.
            set(result);
        } else {
            releaseShared(0); // cancel
        }
    }




// 在AsyncTask的構造函數中, mWorker對象初始化時, 已經覆蓋了call方法, 代碼如下
    public Result call() throws Exception {
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// 3. 調用了用戶實現的doInBackground方法, 去執行一個耗時的任務. 運行在子線程中.
// doInBackground接收的參數就是execute方法接收的參數.
        return doInBackground(mParams);
    }








----------




    protected void set(V v) {
// 5. 繼續把參數傳遞給innerSet方法.
        sync.innerSet(v);
    }


    void innerSet(V v) {
        for (;;) {
            int s = getState();
            if (s == RAN)
                return;
            if (s == CANCELLED) {
                // aggressively release to set runner to null,
                // in case we are racing with a cancel request
                // that will try to interrupt runner
                releaseShared(0);
                return;
            }
            if (compareAndSetState(s, RAN)) {
// 6. 把doInBackground返回的結果賦值給成員變量result
                result = v;
                releaseShared(0);
// 7. 調用FutureTask中的done方法.
                done();
                return;
            }
        }
    }




----------




// 此方法定義在AsyncTask的構造函數中, 初始化mFuture時,已經覆蓋了done方法, 代碼如下:
@Override
    protected void done() {
        Message message;
        Result result = null;


        try {
// 8. 調用FutureTask中的get方法獲取result(doInBackground返回的結果).
            result = 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) {
            message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
                    new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));
            message.sendToTarget();
            return;
        } catch (Throwable t) {
            throw new RuntimeException("An error occured while executing "
                    + "doInBackground()", t);
        }


// 11. 創建一個消息對象.
// msg.what = MESSAGE_POST_RESULT;
// msg.obj = new AsyncTaskResult<Result>(AsyncTask.this, result);
        message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult<Result>(AsyncTask.this, result));
// 12. 把當前消息使用sHandler發送出去.
        message.sendToTarget();
    }


public V get() throws InterruptedException, ExecutionException {
// 9. 轉調innerGet方法.
        return sync.innerGet();
    }


    V innerGet() throws InterruptedException, ExecutionException {
        ...


// 10. 把result(doInBackground的結果)返回回去. result成員變量是在innerSet方法中賦值. 詳情看第6步.
        return result;
    }




----------


    private static class InternalHandler extends Handler {
   @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
   @Override
   public void handleMessage(Message msg) {
// 把obj轉換成AsyncTaskResult類, 這個類中mTask對象就是當前的AsyncTask對象. mData對象就是doInBackground的返回結果.
       AsyncTaskResult result = (AsyncTaskResult) msg.obj;
       switch (msg.what) {
           case MESSAGE_POST_RESULT:
               // There is only one result
// 13. 調用AsyncTask中的finish方法, 並且把doInBackground的返回結果傳遞進去.
               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;
       }
   }
}


    private void finish(Result result) {
        if (isCancelled()) result = null;
// 14. 把doInBackground的返回結果傳遞給用戶實現的onPostExecute方法. 運行在主線程中, 用戶可以做一些操作界面, 更新界面的操作.
        onPostExecute(result);
        mStatus = Status.FINISHED;
    }


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