美文网首页
动手实现AsyncTask v1.1

动手实现AsyncTask v1.1

作者: keyboard3 | 来源:发表于2017-07-23 23:10 被阅读13次

    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();
            }
        };
    

    相关文章

      网友评论

          本文标题:动手实现AsyncTask v1.1

          本文链接:https://www.haomeiwen.com/subject/hqbukxtx.html