動手實現AsyncTask v1.1

AsyncTask.java
AsycnTask-Api
AsyncTask是后臺執行操作在UI線程發布結果的對象,很輕松的使用UI線程,用于耗時較短的后臺操作。

AsyncTask原理

  • AsyncTas類初始化sDefaultExecutor和sHandler變量,用于執行后臺執行任務和分發消息給主線程

  • AsyncTask對象創建時實現后臺執行函數doInBackground()和發布UI結果的回調函數onPostExecute()

  • 構造AsyncTask時

  • 構建類型為WorkerRunnable的mWork對象,執行doInBackground(),然后發送結束消息給sHandler

  • 構建類型FutureTask的mFuture對象,以mWork為回調參數,并重寫任務結束回調方法done(),如果上面沒有發送消息沒有成功會再次發給sHandler

  • mWork和mFuture中發送消息都調用postResult(),message的obj指向的是AsyncTaskResult對象,其包含AsyncTask對象和消息類型標記

  • execute()啟動時在執行線程池處理任務之前先調用onPreExecute()

  • mFuture進入sDefaultExecutor線程池任務隊列消費

  • 任務執行結束調用FutureTask的done()方法,將執行完畢消息通過postResult()發送給sHandler

  • sHandler收到消息根據what標記分別調用asyncTask對象的發布結果回調方法和更新UI進度方法

注明:
AsyncTask必須在主線程中創建
后臺執行回調調用publishProgress()就是發送更新進度消息給sHandler

動手實現

public abstract class AsyncTask<Params, Progress, Result> {
    private static final int MESSAGE_POST_RESULT = 1;//結束標記
    private static final int MESSAGE_POST_PROGRESS = 2;//更新進度標記

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();//cpu核心數

    //最少2個或者4個核心線程
    //cpu核心數少一個線程,以免飽和
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE_SECONDS = 30;

    //線程創建工廠
    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            ////參數2為線程名字
            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
        }
    };
    //最多容納128個任務,再多任務就會被阻塞
    private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(128);

    static {
        //初始化線程執行器配置
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory);
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        sDefaultExecutor = threadPoolExecutor;//暫不使用哪個串行執行的執行器
    }

    private static volatile Executor sDefaultExecutor;
    private static InternalHandler sHnadler;

    //不適用懶加載直接使用
    static {
        sHnadler = new InternalHandler();
    }

    private final WorkerRunnable<Params, Result> mWorker;
    private final FutureTask<Result> mFuture;

    public AsyncTask() {
        //mWorker的參數在execute的時候補上
        mWorker = new WorkerRunnable<Params, Result>() {
            @Override
            public Result call() throws Exception {
                Result result = doInBackground(mParams);//調用后臺執行操作
                postResult(result);//通知handler調用發布結果回調
                return result;
            }
        };
        mFuture = new FutureTask<Result>(mWorker);//暫不包裝二次檢查發送
    }

    //發送結束消息給handler
    private void postResult(Result result) {
        Message message = Message.obtain();
        message.what = MESSAGE_POST_RESULT;
        message.obj = new AsyncTaskResult(this, result);

    }

    //發送更新消息給handler
    protected void publishProgress(Progress... values) {
        Message message = Message.obtain();
        message.what = MESSAGE_POST_PROGRESS;
        message.obj = new AsyncTaskResult(this, values);
    }

    //執行任務
    public void execute(Params... values) {
        onPreExecute();
        mWorker.mParams = values;
        sDefaultExecutor.execute(mFuture);
    }

    protected void onPreExecute() {
    }

    //后臺操作回調
    protected abstract Result doInBackground(Params... var1);

    //發布結果回調
    protected void onPostExecute(Result result) {
    }

   //進度回調
    protected void onProgressUpdate(Progress... values) {
    }

    //主線程處理消息調用asyncTask的回調
    private static class InternalHandler extends Handler {

        public InternalHandler() {
            super(Looper.getMainLooper());
        }

        @Override
        public void handleMessage(Message msg) {
            AsyncTaskResult result = (AsyncTaskResult) msg.obj;
            switch (msg.what) {
                case MESSAGE_POST_RESULT:
                    result.mTask.onPostExecute(result.mData[0]);//發布結果回調
                    break;
                case MESSAGE_POST_PROGRESS:
                    result.mTask.onProgressUpdate(result.mData);//更新進度回調
                    break;
            }
        }
    }

    //通過線程傳遞給doInBackground用戶定義好的參數
    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
        Params[] mParams;
    }

    //消息攜帶類
    private static class AsyncTaskResult<Result> {
        AsyncTask mTask;//消息發送所屬AsyncTask
        Result[] mData;//結果參數

        public AsyncTaskResult(AsyncTask mTask, Result... mData) {
            this.mTask = mTask;
            this.mData = mData;
        }
    }
}

使用

asyncTask.execute("http://www.baidu.com");
...
    AsyncTask<String, Long, String> asyncTask = new AsyncTask<String, Long, String>() {
        @Override
        protected String doInBackground(String... strings) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello";
        }

        @Override
        protected void onPostExecute(String value) {
            super.onPostExecute(value);
            Toast.makeText(MainActivity.this, value + " over", Toast.LENGTH_SHORT).show();
        }
    };
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容