zoukankan      html  css  js  c++  java
  • Android AsyncTask 源代码分析

    AsyncTask源代码分析

    public abstract class AsyncTask<Params, Progress, Result> {
    
        //日志TAG
        private static final String LOG_TAG = "AsyncTask";
    
        //池中所保存的线程数,包括空闲线程。
        private static final int CORE_POOL_SIZE = 5;
        //池中允许的最大线程数。
        private static final int MAXIMUM_POOL_SIZE = 128;
        //当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
        private static final int KEEP_ALIVE = 1;
    
        //一个线程工厂,用来创建新线程 没啥好说的。
        private static final ThreadFactory sThreadFactory = new ThreadFactory() {
            //这个类是一个线程安全的计数器,用到Unsafe直接与底层打交道。
            private final AtomicInteger mCount = new AtomicInteger(1);
    
            //接口实现的方法,就是给线程起了个名字。
            public Thread newThread(Runnable r) {
                return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
            }
        };
    
        //一个固定长度的LinkedBlockingQueue(队列),长度为10。
        private static final BlockingQueue<Runnable> sPoolWorkQueue =
                new LinkedBlockingQueue<Runnable>(10);
    
        //一个线程池,关于这个类的细节可以单独研究,这里不细说,就跟连接池的思想一样
        //里面维护着一些线程 可以同时处理一些任务。
        public static final Executor THREAD_POOL_EXECUTOR
                = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                        TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
    
    
        //创建一个实现了Executor接口的类 这个类的介绍在下面
        public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
    
        //Message的消息类型
        private static final int MESSAGE_POST_RESULT = 0x1;
        private static final int MESSAGE_POST_PROGRESS = 0x2;
    
        //通知主线程的Handler,细节在下面有解释
        private static final InternalHandler sHandler = new InternalHandler();
    
        //就是把上面的SERIAL_EXECUTOR拿过来了,和上面的一样
        private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
    
        //实现了Callable接口 添加了一个参数Params
        private final WorkerRunnable<Params, Result> mWorker;
    
        //封装具体的任务,这个类的细节可以单独研究 这里也不做细说。
        //这个类的特点就是可以取消并且可以监控任务状态
        private final FutureTask<Result> mFuture;
    
        //将状态设置成【还没开始执行】的状态
        private volatile Status mStatus = Status.PENDING;
        
        //标记任务是否已经取消,后面的一些方法需要用到。
        private final AtomicBoolean mCancelled = new AtomicBoolean();
        //标记任务是否已经执行,后面的一些方法需要用到。
        private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
    
        //实现Executor接口 对Runnable(任务)在进行一次封装
        //这样的实现可以使任务保持连续,即第一个任务执行完毕接着会执行第二个任务
        //第二个任务执行在执行第三个任务,以此类推。
        private static class SerialExecutor implements Executor {
            //一个数组双端队列没有容量限制
            final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
            //当前正在执行的任务
            Runnable mActive;
    
            //这里进行了synchronized,因为ArrayDeque不是线程安全的,对它的操作需要同步。
            public synchronized void execute(final Runnable r) {
                //对任务进行包装,然后加入队列的末尾。
                mTasks.offer(new Runnable() {
                    public void run() {
                        try {
                            //执行具体任务
                            r.run();
                        } finally {
                            //执行下一个任务【编号001】
                            scheduleNext();
                        }
                    }
                });
                //如果当前没有执行的任务,则调用scheduleNext开始执行任务
                //如果不为null 说明已经有任务在执行,那么就不需要调用scheduleNext
                //因为当前任务会被上一个任务在完成时调用。即在【编号001】的位置。
                if (mActive == null) {
                    scheduleNext();
                }
            }
    
            //从队列的头部拿出一个元素,然后执行。这里的任务是在上面包装过的。
            //它会先执行具体任务,然后再执行下一个任务
            protected synchronized void scheduleNext() {
                if ((mActive = mTasks.poll()) != null) {
                    THREAD_POOL_EXECUTOR.execute(mActive);
                }
            }
        }
    
        //当前类的状态
        public enum Status {
            //还没开始执行
            PENDING,
            //执行中
            RUNNING,
            //任务完成
            FINISHED,
        }
    
        //没啥用
        public static void init() {
            sHandler.getLooper();
        }
    
        //没啥用
        public static void setDefaultExecutor(Executor exec) {
            sDefaultExecutor = exec;
        }
    
        //构造参数必须运行在UI线程
        public AsyncTask() {
            //创建一个WorkerRunnable实例
            //这里用到了FutureTask与Callable相关技术。需要自己去研究下
            mWorker = new WorkerRunnable<Params, Result>() {
                public Result call() throws Exception {
                    //一旦具体任务执行,就将这个标记置为true
                    mTaskInvoked.set(true);//【编号002】
                    //设置当前线程优先级为后台线程
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    //首先调用doInBackground这个方法 就是我们需要复写的方法。
                    //然后调用postResult方法 并将doInBackground的返回值传入。
                    return postResult(doInBackground(mParams));
                }
            };
    
            //创建一个任务FutureTask,并将上面的mWorker通过构造参数传入。
            mFuture = new FutureTask<Result>(mWorker) {
                //覆写了done方法,这样当任务的状态发生变化时可以进行监控。
                //当任务完成时或取消都进入该方法
                @Override
                protected void done() {
                    try {
                        //通过get方法获取任务的返回结果
                        //下面就分2中情况
                        //1-如果上面的call方法正确被调用 那么就执行postResultIfNotInvoked方法
                        //2-如果任务被取消或者任务执行过程中出现异常则会抛出异常,在下面catch到在进行处理
                        postResultIfNotInvoked(get());
                    } catch (InterruptedException e) {
                        android.util.Log.w(LOG_TAG, e);
                    } catch (ExecutionException e) {
                        //如果在doInBackground方法中存在异常 这里会继续抛出
                        throw new RuntimeException("An error occured while executing doInBackground()",
                                e.getCause());
                    } catch (CancellationException e) {
                        //如果方法被取消,那么调用postResultIfNotInvoked并传入null
                        postResultIfNotInvoked(null);
                    }
                }
            };
        }
    
        private void postResultIfNotInvoked(Result result) {
            final boolean wasTaskInvoked = mTaskInvoked.get();
            //这里判断wasTaskInvoked标记,判断任务是否已经正常结束
            //如果在mWorker的call方法正确执行 那么在【编号002】的位置会把wasTaskInvoked设置为true
            //这样的话在done()方法中的postResultIfNotInvoked(get());方法才不会重复执行
            //也就是说方法如果在mWorker的call方法中执行了 那么在done()中在调用postResultIfNotInvoked(get());
            //方法在执行到这的话就不会执行了,反之亦然。
            if (!wasTaskInvoked) {
                postResult(result);
            }
        }
    
        //该方法是把任务结果发送给UI线程去执行
        //就是Looper Handler Message 没啥好说的
        private Result postResult(Result result) {
            @SuppressWarnings("unchecked")
            Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
                    new AsyncTaskResult<Result>(this, result));
            message.sendToTarget();
            return result;
        }
    
        //过去当前任务的执行状态
        public final Status getStatus() {
            return mStatus;
        }
    
    
        //需要子类付覆写的方法,后台线程运行。
        protected abstract Result doInBackground(Params... params);
    
    
        //在doInBackground方法执行运行,UI线程运行该方法。
        //可以启动个进度条之类的操作可以写在这里。
        protected void onPreExecute() {
        }
    
    
        //UI线程执行,在doInBackground放执行以后执行。
        //要注意的是在任务没有出现异常 也没有被取消的情况下才会执行
        //否则执行onCancelled
        @SuppressWarnings({"UnusedDeclaration"})
        protected void onPostExecute(Result result) {
        }
    
    
        //运行在UI线程 通过在doInBackground中调用publishProgress方法通知UI线程做一些处理
        //比如更新带百分比的进度条等
        @SuppressWarnings({"UnusedDeclaration"})
        protected void onProgressUpdate(Progress... values) {
        }
    
    
        @SuppressWarnings({"UnusedParameters"})
        protected void onCancelled(Result result) {
            onCancelled();
        }    
        
        //一般子类覆写这个方法 就是cancel方法被调用后 任务被取消 则会执行该方法
        protected void onCancelled() {
        }
    
    
        //获取任务是否取消
        public final boolean isCancelled() {
            return mCancelled.get();
        }
    
        //终止任务
        //参数的意义是这样的
        //如果线程还没有被启动,那么无论mayInterruptIfRunning是啥 任务都会被取消
        //如果任务已经启动 那么如果mayInterruptIfRunning=true 那么会调用线程的
        //interrupt方法,这个方法是的解释可以看API 太多了 这里不细说。
        public final boolean cancel(boolean mayInterruptIfRunning) {
            mCancelled.set(true);
            return mFuture.cancel(mayInterruptIfRunning);
        }
    
    
        //这个方法获取任务的结果,是一个阻塞方法
        //属于FutureTask的范畴
        public final Result get() throws InterruptedException, ExecutionException {
            return mFuture.get();
        }
    
        //同上
        public final Result get(long timeout, TimeUnit unit) throws InterruptedException,
                ExecutionException, TimeoutException {
            return mFuture.get(timeout, unit);
        }
    
        //启动任务
        public final AsyncTask<Params, Progress, Result> execute(Params... params) {
            //调用executeOnExecutor
            return executeOnExecutor(sDefaultExecutor, params);
        }
    
        //这个方法是AsyncTask的启动方法,用来启动任务
        public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
                Params... params) {
            //判断任务的状态 如果不是PENDING状态则抛出异常
            //也就是说任务只能启动一次,不可重复启动。
            if (mStatus != Status.PENDING) {
                switch (mStatus) {
                    case RUNNING:
                        throw new IllegalStateException("Cannot execute task:"
                                + " the task is already running.");
                    case FINISHED:
                        throw new IllegalStateException("Cannot execute task:"
                                + " the task has already been executed "
                                + "(a task can be executed only once)");
                }
            }
    
            //设置任务状态为RUNNING
            mStatus = Status.RUNNING;
            //调用预处理方法上面解释过。
            onPreExecute();
            //给mWorker设置参数
            mWorker.mParams = params;
            //将任务加入到sDefaultExecutor当中去执行
            exec.execute(mFuture);
            //返回自己
            return this;
        }
    
        //这个方法是用过sDefaultExecutor执行直接执行一个Runnable接口,去AsyncTask没啥关系
        //无非就是用到了sDefaultExecutor
        public static void execute(Runnable runnable) {
            sDefaultExecutor.execute(runnable);
        }
    
        //这个方法可以通知UI线程更新进度
        protected final void publishProgress(Progress... values) {
            if (!isCancelled()) {
                sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
                        new AsyncTaskResult<Progress>(this, values)).sendToTarget();
            }
        }
    
        //任务完成后调用的方法,会根据isCancelled()的返回值判断任务是否被取消或者正常执行成功。
        private void finish(Result result) {
            if (isCancelled()) {
                onCancelled(result);
            } else {
                onPostExecute(result);
            }
            mStatus = Status.FINISHED;
        }
    
        //Handler没啥好说的
        private static class InternalHandler extends Handler {
            @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
            @Override
            public void handleMessage(Message msg) {
                AsyncTaskResult result = (AsyncTaskResult) msg.obj;
                switch (msg.what) {
                    case MESSAGE_POST_RESULT:
                        // There is only one result
                        result.mTask.finish(result.mData[0]);
                        break;
                    case MESSAGE_POST_PROGRESS:
                        result.mTask.onProgressUpdate(result.mData);
                        break;
                }
            }
        }
    
        //一个抽象类实现了Callable<Result>接口 添加了参数。
        private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
            Params[] mParams;
        }
    
        //一个用于封装任务与结果的类
        @SuppressWarnings({"RawUseOfParameterizedType"})
        private static class AsyncTaskResult<Data> {
            final AsyncTask mTask;
            final Data[] mData;
    
            AsyncTaskResult(AsyncTask task, Data... data) {
                mTask = task;
                mData = data;
            }
        }
    }

     

    AsyncTask 核心原理大概如下

    InternalHandler sHandler = new InternalHandler(); 这个handler是主线程初始化的,用来调用更新UI的方法。

    THREAD_POOL_EXECUTOR 一个线程池用来处理异步任务。

    sPoolWorkQueue 一个任务队列,我们发起的所有任务都会放到这个队列当中,由THREAD_POOL_EXECUTOR 它来进行处理。

    流程就是当我们创建一个AsyncTask实例 ,那么AsyncTask会生成一个任务对象(Runnable)放入sPoolWorkQueue 这个队列当中,然后有THREAD_POOL_EXECUTOR 线程池去进行异步处理,在处理的过程中通过sHandler 通知主线程去调用我们复写的那几个方法更新UI。

    这个类在设计当中还使用到了 FutureTask 

    关于这个类的源码分析请看我的另外一个博客:http://www.cnblogs.com/daxin/p/3802392.html

  • 相关阅读:
    python读取xml文件报错ValueError: multi-byte encodings are not supported
    使用命令创建jenkins的job,解决jenkinsapi.custom_exceptions.JenkinsAPIException错误
    使用Python命令创建jenkins的job
    使用selenium grid分布式执行之一
    使用python 操作liunx的svn,方案二
    使用python 操作liunx的svn,方案一
    使用shell脚本实现在liunx上进行svn的上传下载更新功能
    java连接ssh执行shell脚本
    perl学习(二)正则表达式
    googletest进行单元测试(使用cmake编译)
  • 原文地址:https://www.cnblogs.com/daxin/p/3500822.html
Copyright © 2011-2022 走看看