美文网首页
自定义一个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