AsyncTask的源碼分析 與 使用 之我的淺解

       由於主線程負責處理用戶輸入事件, 如果主線程被阻塞,應用就會報ANR錯誤.爲了不阻塞主線程,我們需要在子線程中處理耗時的操作,在處理耗時操作的過程中,子線程可能需要更新UI控件的顯示, 由於UI控件的更新重繪是由主線程負責的,所以子線程需要通過Handler發送消息到主線程的消息對列中, 由運行在主線程的消息處理代碼接收到消息後更新UI控件的顯示.

    採用線程+Handler實現異步處理時,當每次執行耗時操作都創建一條新線程進行處理,性能開銷會比較大, 如果耗時操作執行的時間比較長,就有可能同時運行着許多線程,系統終將不堪重負. 爲了提高性能我們使用AsyncTask實現異步處理,事實上其內部也是採用線程+handler來實現異步處理的.只不過是其內部使用了JDK5提供的線程池技術,有效的降低了線程創建數量及限定了同時運行的線程數,還有一些針對性的對池的優化操作.

 

AsyncTask內部使用了JDK5後的線程池ThreadPoolExecutor,在內部自定義配置了AsyncTask的專用線程池sExecutor執行者。而這種線程池的配置需要對系統和業務的理解來定的.我們一般默認最好,而JDK也建議我們使用它提供的幾個已經封裝好的類.

還是先看一看關於AsyncTask的代碼

public abstract class AsyncTask<Params, Progress, Result> {
    private static final String LOG_TAG = "AsyncTask";
    //核心線程數5;
    private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;//最大線程數128
// 當線程數大於核心時,終止當前多餘的空閒線程等待新任務的最長時間10(單位未知)
private static final int KEEP_ALIVE = 10; 
//創建10容量的基於已鏈接節點的、範圍任意的 blocking queue。此隊列按 FIFO(先進先出)排序元素
    private static final BlockingQueue<Runnable> sWorkQueue =
            new LinkedBlockingQueue<Runnable>(10);
//定製內部線程池的生成線程的簡單工廠,併爲每個任務指定 了一個遞增的唯一的id
    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());
        }
    };
/**
 * 創建線程池(看配置好像是文檔中所說的小隊列較大池policy)
 */
    private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
            MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);

    private static final int MESSAGE_POST_RESULT = 0x1;
    private static final int MESSAGE_POST_PROGRESS = 0x2;
    private static final int MESSAGE_POST_CANCEL = 0x3;
   //又在內部準備了一個處理器(由於這個AsyncTask在UI線程中使用,所以這個InternalHandler是主線程的啦)
    private static final InternalHandler sHandler = new InternalHandler();
   //工作任務封裝類
    private final WorkerRunnable<Params, Result> mWorker;
    private final FutureTask<Result> mFuture;
   //volatile類型的枚舉值, 默認表示爲PENDING未執行狀態
    private volatile Status mStatus = Status.PENDING;

    /**
     * Indicates the current status of the task. Each status will be set only once
     * during the lifetime of a task.
     */
    public enum Status {
        /**
         * Indicates that the task has not been executed yet.
         */
        PENDING,
        /**
         * Indicates that the task is running.
         */
        RUNNING,
        /**
         * Indicates that {@link AsyncTask#onPostExecute} has finished.
         */
        FINISHED,
    }
//構造方法

/**
     * Creates a new asynchronous task
* This constructor must be invoked on the UI thread.
     */
    public AsyncTask() {
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                //設置任務執行的優先級比默認線程優先級略低一些
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                return doInBackground(mParams); //回調doInBackGround(數組)方法
            }
        };
        //用mWorker創建一個可取消的異步計算任務
        mFuture = new FutureTask<Result>(mWorker) {
            //當任務不管是正常終止、異常或取消而完成的,都回調此方法, 即isDone()爲true時
            @Override
            protected void done() {
                Message message;
                Result result = null;

                try {
                    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) {
                    //當發生CancellationException異常時說明任務被取消了, 消息通知UI線程
                    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);
                }
                //正常結束任務後發消息執行MESSAGE_POST_RESULT的回調操作
                message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
                        new AsyncTaskResult<Result>(AsyncTask.this, result));
                message.sendToTarget();
            }
        };
    }



public final Result get(long timeout, TimeUnit unit) throws InterruptedException,
            ExecutionException, TimeoutException {
        return mFuture.get(timeout, unit);
    }


//這是AsyncTask異步任務的啓動方法
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        //首先判斷AsyncTask異步任務的狀態,當處於RUNNING和FINISHED時就報IllegalStateException非法狀態異常
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;
        sExecutor.execute(mFuture);

        return this;
    }


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

    private void finish(Result result) {
        if (isCancelled()) result = null;
        onPostExecute(result);
        mStatus = Status.FINISHED;
    }
    //這個就是它的內部回調機制的回調方法處理
    private static class InternalHandler extends Handler {
        @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;
                case MESSAGE_POST_CANCEL:
                    result.mTask.onCancelled();
                    break;
            }
        }
    }

    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
        Params[] mParams;
    }
     //對結果的封裝
    @SuppressWarnings({"RawUseOfParameterizedType"})
    private static class AsyncTaskResult<Data> {
        final AsyncTask mTask;
        final Data[] mData;

        AsyncTaskResult(AsyncTask task, Data... data) {
            mTask = task;
            mData = data;
        }
    }

好了這就是AsyncTask的全部代碼,裏面省略了部分回調和基本的獲取任務信息的代碼,而這此也都是對JDK5併發庫中類的封裝使用,有興趣的可以看看,這裏不做過多解釋.

首先來理一下AsyncTask的執行過程.

1, 首先我們一般先在主線程中創建一個AsyncTask類的匿名內部類, 並指明它的三個範型的參數化類型.

         而在其構造方法中做了一件事,準備了一個將要執行的可取消的任務賦值給mFuture,

首先實現了WorkerRunnable 抽象類mWorker,並在其call執行方法中回調在後臺執行的doInBackground()方法並params預設給這個方法.

然後用這個mWorker準備創建new FutureTask<Result>(mWorker)並在其done()方法中用result =get();等待執行的結果,當這個後臺執行的FutureTask被取消後並捕獲到CancellationException異常就用InternalHandler類型的sHandler向主線程發送標誌爲MESSAGE_POST_CANCEL|結果爲Null的消息.而任務被正常執行完成後向主線程發送MESSAGE_POST_RESULT|結果爲result的消息.

2, 在匿名內部類中我們重寫四個onPostExecute, onPreExecute, onProgressUpdate, onCancelled

        在主線程執行的方法, 和 一個doInBackground實際後臺工作的方法

3, 當我們做完這一切後,調用execute(params)首先設置狀態sStataus爲Status.RUNNING,執行onPreExecute();回調,然後將params賦值給WorkerRunnable的params數組最後將構造中準備好的mFuture交給線程池中執行.

4. 剩下的事就是在done中等待執行結果.然後向主線程發送消息.而處理器已經準備了三種消息類別分別對應了不同的響應:

1) MESSAGE_POST_RESULT: onPostExecute(result);

2) MESSAGE_POST_PROGRESS: onProgressUpdate(result.mData);

                  3) MESSAGE_POST_CANCEL: onCancelled()

還有一個問題我注意到MESSAGE_POST_PROGRESS我看到是在publishProgress方法中發送的.

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

        sHandler.obtainMessage(MESSAGE_POST_PROGRESS,

                newAsyncTaskResult<Progress>(this, values)).sendToTarget();

    }

而在AsyncTask類內部並沒有對這個publishProgress方法的調用而這個方法又是protected的,通過查看文檔這個方法的最佳調用時機是在doInBackground方法中向UI主線程publish updates,

 

另外也必須強調的是AsyncTask這個抽象類內部只用一個protected abstract Result doInBackground(Params... params);的抽象方法,在實現這個類的時候是必須要準備好這個後臺執行的方法,其他可選.

 

寫到這也差不多了,

再向大家介紹我對AsyncTask類的簡單封裝使用方法(當在應用中多處使用同樣的異步任務時可以考慮)

首先把這個異步任務類獨立出來,並類的構造中指定自定義的接口實現

public class MyAsyncTask extends AsyncTask <Params, Progress, Result>{
	
	private ResponseInterface response;
	public MyAsyncTask (ResponseInterface response) {
		this.response = response;
	}
	/**
	 * 對asyncTask任務的簡單封裝的接口,
	 * 在使用此任務時主線程的工作就放在這個接口方法中實現
	 * 後臺任務交給該任務的doInBackground
	 */
	public interface ResponseInterface{
		void preRunning();
		void finished(Result result);
	}
	/**
	 * 任務執行前
	 */
	@Override
	protected void onPreExecute() {
		response. preRunning ();
		super.onPreExecute();
	}
	/**
	 * 任務執行後
	 */
	@Override
	protected void onPostExecute(Result result) {
		if(null != result){
			response. finished (result);
		}
		super.onPostExecute(result);
	}

	@Override
	protected Boolean doInBackground(Params... params) {
		//doSomething();
		return true;
	}
 
	/**
	 * 任務執行進度更新
	 */
	@Override
	protected void onProgressUpdate(Progress... values) {

		super.onProgressUpdate(values);
	}

	/**
	 * 任務完取消後執行
	 */
	@Override
	protected void onCancelled() {
		
		super.onCancelled();
	}
}

這樣的話後臺執行的業務邏輯與前臺UI的執行就分離出來的,在使用時只要new出這個AsyncTask異步任務類並指定這個內部接口的實現類就可以了,在前臺只做前臺的事,後臺則交給這個自定義的AsyncTask異步任務類來實現.

 




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