美文网首页
自定义一个AsyncTask

自定义一个AsyncTask

作者: 杨殿生 | 来源:发表于2018-08-22 14:38 被阅读0次

    上一篇我们分析类AsyncTask原理,但想要真正的掌握还是要动手自己实现一个AsyncTask,下面我们就开始参照AsyncTask源码一步一步的自己动手写一个,毕竟参照大神的写代码才能进步最快,就起名YdsAsyncTask,为啥多了一个yds懒得想名就拿自己的名字做下区分

    AsyncTask实现

    1,写一个抽象类,实现在子线程要调用的抽象方法
    //这里使用泛型限定参数,进度,和返回值
    public abstract class YdsAsyncTask<Params,Progress,Result> {
        //子线程中要执行的方法接收泛型可变参数,返回要返回的值
        public abstract Result doInBackGround(Params... params);
    }
    
    2,主线程Handler用于主线程通知更新
    private static class InternalHandler extends Handler {
            public InternalHandler(Looper looper){
                super(looper);
            }
        }  
        //主线程Handler用于通知进度更新
        private static Handler mInternalHandler;
        public YdsAsyncTask(){
            mInternalHandler = getMainHandler();
        }
        //获取主线程handler用于更新主线程进度
        public Handler getMainHandler() {
            synchronized (YdsAsyncTask.class){
                if (mInternalHandler == null){
                    mInternalHandler = new InternalHandler(Looper.getMainLooper());
                } 
                return mInternalHandler;
            }
        }
    
    3,子线程WorkerRunnable用于传递参数,和运行子线程执行代码
     //用于子线程运行子线程执行的回调
        private static abstract class WorkRunnable<Params,Result> implements Callable<Result>{
            Params[] mParams;
        }
    
        //主线程Handler用于通知进度更新
        private static Handler mInternalHandler;
        private final WorkRunnable<Params,Result> mWorker:
    
        public YdsAsyncTask(){
            mInternalHandler = getMainHandler();
            mWorker = new WorkRunnable<Params, Result>() {
                @Override
                public Result call() throws Exception {
                    Result result = null;
                    try {
                        result = doInBackGround(mParams);
                    } finally {
    
                    }
                    return result;
                }
            };
        }
    
    4,创建FutureTask用于控制WorkerRunnable
    mFutrueTask = new FutureTask<Result>(mWorker){
                @Override
                protected void done() {
                    super.done();
                    //这里在线程执行结束后会返回结果
                    try {
                        postResult(get());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        postResult(null);
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                        postResult(null);
                    }
                }
            };
    

    在执行完workerRunnable后会执行done中方法,经过postResult发送消息,在子线程中调用doPostExecute()
    doPostExecute()

     private Result postResult(Result result){
            Message message = mInternalHandler.obtainMessage(MESSAGE_POST_RESULT,
                    new AsyncTaskResult<Result>(this, result));
            message.sendToTarget();
            return result;
        }
    
    5,执行线程池创建,消息队列的处理

    创建完对象后调用execute(Params... mParams),他最后会调用下面的方法,先执行onPreExecute(),然后将参数赋值给Worker,这个参数里多传了一个sDefaultExecutor来执行代码,那这个是什么呢

      public final YdsAsyncTask<Params,Progress,Result> execute(Params... mParams){
            return executeOnExecutor(sDefaultExecutor,mParams);
        }
    
      private final YdsAsyncTask<Params,Progress,Result> executeOnExecutor(Executor executor,Params... mParams){
            onPreExecute();
            mWorker.mParams = mParams;
            executor.execute(mFutrueTask);
            return this;
        }
    

    处理传入的Executor

        private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
        private static class SerialExecutor implements Executor {
    
            final ArrayDeque<Runnable> mTasks = new ArrayDeque<>();
            Runnable mActive = null;
    
            @Override
            public void execute(final Runnable runnable) {
                mTasks.offer(new Runnable() {
                    @Override
                    public void run() {
                        try{
                            runnable.run();
                        } finally {
                            scheduleNext();
                        }
                    }
                });
                if (mActive == null){
                    scheduleNext();
                }
            }
    
            private synchronized void scheduleNext(){
                //服务下一个
                for (Runnable runnable:mTasks){
                    Log.i("yyy",runnable.toString());
    
                }
                if ((mActive = mTasks.poll()) != null){
                    THREAD_POOL_EXECUTOR.execute(mActive);
                }
            }
        }
    

    当执行时会将执行方法添加到mTasks队列中,然后会在从队列中取出任务调用THREAD_POOL_EXECUTOR.execute(mActive),去真正的执行需要执行的代码,我们看下THREAD_POOL_EXECUTOR如何实现

        //任务服务线程池
        public static final Executor THREAD_POOL_EXECUTOR;
    
        private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
        // We want at least 2 threads and at most 4 threads in the core pool,
        // preferring to have 1 less than the CPU count to avoid saturating
        // the CPU with background work
        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) {
                return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
            }
        };
    
        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);
            THREAD_POOL_EXECUTOR = threadPoolExecutor;
        }
    

    这里没有使用系统的线程池,而是基于ThreadPoolExecutor创建一个自己的threadPoolExecutor的线程池,阻塞队列使用的是LinkedBlockingQueue,

    总结:
    实现一个异步通信并在主线程同时更新view那需要注意一下几点
    1,抽象要子类需要复写的方法
    2,主线程通讯Handler
    3,处理输入任务的队列
    4,使用线程池处理任务队列中的数据

    源码地址:https://github.com/yangdiansheng/YdsTest

    相关文章

      网友评论

          本文标题:自定义一个AsyncTask

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