AsyncTask

作者: 冉桓彬 | 来源:发表于2017-05-24 20:08 被阅读12次

    AsyncTask通常有以下两种调用方式:

    1. AsyncTaskImpl().setTask(RunnableImpl).execute();
    2. AsyncTask.execute(RunnableImpl);
    
    • 仅针对第一种方式进行分析:
    AsyncTask.AsyncTask():
    public AsyncTask() {  
        /**
         * 1. 初始化AsyncTask时会在主线程中创建WorkerRunnable和FutureTask对象;
         * 2. 先跳过FutureTask, 直接分析execute(), 然后从execute()分析FutureTask;
         */
        mWorker = new WorkerRunnable<Params, Result>() {...};
        mFuture = new FutureTask<Result>(mWorker) {...};
    }
    
    WorkerRunnable :
    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
        Params[] mParams;
    }
    public interface Callable<V> {
        V call() throws Exception;
    }
    
    AsyncTask.execute() :
    public class AsyncTask {
        public final AsyncTask<...> execute(Params... params) {
            return executeOnExecutor(sDefaultExecutor, params);
        }
        private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
        public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
        private static class SerialExecutor implements Executor {...}
    }
    
    AsyncTask.executeOnExecutor() :
    public class AsyncTask {
        public final AsyncTask<...> executeOnExecutor(Executor exec, ...) {
            /**
             * 1. mStatus初始化时被赋值Status.PENDING, 由下文可知没Status只有三个可
             * 能的值: PENDING/RUNNING/FINISHED, 当前任务执行完毕, mStatus被赋值
             * FINISHED, 当任务执行中时RUNNING, 所以当再次调用execute()时, 会抛出异
             * 常, 这种方式下的AsyncTask仅仅适合单个任务, 不适
             * 用于多线程的场景;
             * 2. 如果想要按顺序的执行多个AsyncTask, 可以使用方式2_AsyncTask.execute(RunnableImpl);
             */
            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)");
                }
            }
            mStatus = Status.RUNNING;
            /**
             * 在主线程中执行;
             */
            onPreExecute();
            mWorker.mParams = params;
            /**
             * FutureTask的分析从此揭开序幕;
             */
            exec.execute(mFuture);
            return this;
        }
    }
    
    AsyncTask.mFuture :
    public class AsyncTask {
        public AsyncTask() {
            mWorker = new WorkerRunnable<Params, Result>() {
                public Result call() throws Exception {
                    mTaskInvoked.set(true);
                    Result result = null;
                    try {
                        result = doInBackground(mParams);
                        Binder.flushPendingCommands();
                    } catch (Throwable tr) {
                        mCancelled.set(true);
                        throw tr;
                    } finally {
                        postResult(result);
                    }
                    return result;
                }
            };
    
            mFuture = new FutureTask<Result>(mWorker) {
                @Override
                protected void done() {
                    try {
                        postResultIfNotInvoked(get());
                    } catch (InterruptedException e) {
                        android.util.Log.w(LOG_TAG, e);
                    } catch (ExecutionException e) {
                        throw new RuntimeException("An error occurred while executing doInBackground()",
                                e.getCause());
                    } catch (CancellationException e) {
                        postResultIfNotInvoked(null);
                    }
                }
            };
        }
        private static class SerialExecutor implements Executor {
            final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
            Runnable mActive;
            /**
              * 由ArrayDeque内部结构可以知道当执行一个Runnable时, 会先将改Runnable添
              * 加至ArrayDeque内部数组的尾部, 然后从数组的头部读取Runnable执行, 即按
              * 照FILO的方式;
              */
            public synchronized void execute(final Runnable r) {
                /**
                 * 对于方式1, 也仅考虑方式1(方式2直观没有什么地方值得研究);  此时Runnable
                 * 实际指向mFuture, 而mFuture内部又持有WorkerRunnable的引用;
                 * mActive实际指向mFuture;
                 * 这里主要用到了适配器的模式;
                 */
                mTasks.offer(new Runnable() {
                    public void run() {
                        try {
                            r.run();
                        } finally {
                            scheduleNext();
                        }
                    }
                });
                if (mActive == null) {
                    scheduleNext();
                }
            }
    
            protected synchronized void scheduleNext() {
                if ((mActive = mTasks.poll()) != null) {
                    THREAD_POOL_EXECUTOR.execute(mActive);
                }
            }
        }
    }
    
    public interface RunnableFuture<V> extends Runnable, Future<V> {
        void run();
    }
    
    public interface Future<V> {
        boolean cancel(boolean mayInterruptIfRunning);
        boolean isCancelled();
        boolean isDone();
        V get() throws InterruptedException, ExecutionException;
        V get(long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
    }
    
    public class FutureTask<V> implements RunnableFuture<V> {
        public FutureTask(Callable<V> callable) {
            this.callable = callable;
            this.state = NEW;   
        }
        public FutureTask(Runnable runnable, V result) {
            this.callable = Executors.callable(runnable, result);
            this.state = NEW; 
        }
        public void run() {
            try {
                Callable<V> c = callable;
                if (c != null && state == NEW) {
                    V result;
                    boolean ran;
                    result = c.call();
                    ran = true;
                    if (ran)
                        set(result);
                }
            } 
        }
    }
    

      这里用到了适配器模式, FutureTask有两个构造函数分别可以接收Callable与Runnable, 但是对外之暴露了一个run()的接口供调用, 如果传的是Callbale, run方法调用了c.call()方法. 如果传入的是Runnable, run()方法则会一波三折, 他先调用c.call()方法, 此时c实际是RunnableAdapter implements Callable, 然后调用的是RunnableAdapter中的call()方法, 然后里面又调用了Runnable的run()方法, 此Runnable就是我们传入的Runnable对象;

    public class Executors {
        public static <T> Callable<T> callable(Runnable task, T result) {
            return new RunnableAdapter<T>(task, result);
        }
        static final class RunnableAdapter<T> implements Callable<T> {
            final Runnable task;
            final T result;
            RunnableAdapter(Runnable task, T result) {
                this.task = task;
                this.result = result;
            }
            public T call() {
                task.run();
                return result;
            }
        }
    }
    

       其实感觉AsyncTask本身是挺简单的, 关键在于他对线程的操控, 这个需要注意一下. 这个现在是真心没法看下去了, 等我把几本关于底层的书看完在说这些事儿吧;

    相关文章

      网友评论

          本文标题:AsyncTask

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