动手实现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 {
    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 sPoolWorkQueue =
            new LinkedBlockingQueue(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 mWorker;
    private final FutureTask mFuture;

    public AsyncTask() {
        //mWorker的参数在execute的时候补上
        mWorker = new WorkerRunnable() {
            @Override
            public Result call() throws Exception {
                Result result = doInBackground(mParams);//调用后台执行操作
                postResult(result);//通知handler调用发布结果回调
                return result;
            }
        };
        mFuture = new FutureTask(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 implements Callable {
        Params[] mParams;
    }

    //消息携带类
    private static class AsyncTaskResult {
        AsyncTask mTask;//消息发送所属AsyncTask
        Result[] mData;//结果参数

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

使用

asyncTask.execute("http://www.baidu.com");
...
    AsyncTask asyncTask = new AsyncTask() {
        @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();
        }
    };

你可能感兴趣的:(动手实现AsyncTask v1.1)