AsyncTask源码整理一波

作者: 的一幕 | 来源:发表于2019-04-15 18:49 被阅读25次

    在讲源码之前还是习惯性的把demo拿出来写一写:

    static class MyAsyncTask extends AsyncTask<Void, Integer, Boolean> {
        int progress;
        ProgressBar progressBar;
        MyAsyncTask(ProgressBar progressBar) {
            this.progressBar = progressBar;
        }
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
        @Override
        protected Boolean doInBackground(Void... voids) {
            while (progress < 100) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                progress++;
                publishProgress(progress);
            }
            return true;
        }
        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
        }
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            progressBar.setProgress(values[0]);
        }
    }
    

    调用的地方:

    new MyAsyncTask(progressBar).execute();
    

    demo的源代码是在android-28下面的,android studio没有集成28的源码,赶快集成起来吧,这里主要分析onPreExecutedoInBackgroundonPostExecuteonProgressUpdate等方法主要发生的地方。

    源码分析:

    image.png

    AsyncTask是一个抽象类,并且需要指明三个参数的类型,分别是Params、Progress、Result,接着看下AsyncTask构造方法都做了些啥:

    /**
         * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
         */
        public AsyncTask() {
            this((Looper) null);
        }
    
        /**
         * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
         *
         * @hide
         */
        public AsyncTask(@Nullable Handler handler) {
            this(handler != null ? handler.getLooper() : null);
        }
    
        /**
         * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
         *
         * @hide
         */
        public AsyncTask(@Nullable Looper callbackLooper) {
            mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
                ? getMainHandler()
                : new Handler(callbackLooper);
    
            mWorker = new WorkerRunnable<Params, Result>() {
                public Result call() throws Exception {
                    mTaskInvoked.set(true);
                    Result result = null;
                    try {
                        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                        //noinspection unchecked
                        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);
                    }
                }
            };
        }
    

    从上面可以看到调用的是第三个hide类型的构造方法:
    从mHandler的初始化就可以看出来,咋们的handler获取的是getMainHandler

    private static Handler getMainHandler() {
            synchronized (AsyncTask.class) {
                if (sHandler == null) {
                    sHandler = new InternalHandler(Looper.getMainLooper());
                }
                return sHandler;
            }
    }
    

    创建了一个InternalHandler,并且将mainLooper传了进去:

    private static class InternalHandler extends Handler {
            public InternalHandler(Looper looper) {
                super(looper);
            }
    
            @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;
                }
            }
     }
    

    其实就是我们经常写的Handler,这里封装了两种状态,稍后再说该Handler处理的逻辑,咋们还是回到构造函数的创建那,分别创建了一个WorkerRunnable对象和FutureTask变量,WorkerRunnable是一个Callable对象,FutureTask是一个RunnableFuture对象,是RunnableFuture对象的结合:

    image.png
    image.png
    image.png
    其实可以看出来他两的代码WorkerRunnable是一个工作的子线程,类似平常写的runnable功能,FutureTask也是一个WorkerRunnable,用来处理WorkerRunnable。因为我们可以从
    FutureTask看出来,把mWorker对象传给了FutureTask的构造器,后面再细说FutureTask是怎么工作的,以及怎么处理WorkerRunnable的,下面我们直接看AsyncTaskexecute方法:
    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
            return executeOnExecutor(sDefaultExecutor, params);
    }
    

    直接调用了executeOnExecutor方法,并且把sDefaultExecutor传过去了,sDefaultExecutor它是一个SerialExecutor对象。它是一个Executor对象,也就是java中提供的线程池:

    image.png

    先不做过多的该类分析,接着看executeOnExecutor方法:

    @MainThread
    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
                Params... params) {
            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;
            exec.execute(mFuture);
            return this;
    }
    

    先是状态的判断,可以看到第一次调用excute方法会将状态至为RUNNING,多次再调用excute方法会抛异常。
    紧接着调用了onPreExecute方法,所以明白为啥onPreExecute是异步任务之前重写的方法,该方法是个空的实现:

    image.png
    然后将传进来的params给了mWorker对象,下面看下exec.execute(mFuture)方法做了些啥,上面已经知道exec是一个SerialExecutor对象,执行的任务是mFuture,看看SerialExecutorexcute怎么执行mFuture的:
    private static class SerialExecutor implements Executor {
            final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
            Runnable mActive;
    
            public synchronized void execute(final Runnable r) {
                mTasks.offer(new Runnable() {
                    public void run() {
                        try {
                            //mFuture的run方法
                            r.run();
                        } finally {
                            scheduleNext();
                        }
                    }
                });
                if (mActive == null) {
                    scheduleNext();
                }
            }
    
            protected synchronized void scheduleNext() {
                if ((mActive = mTasks.poll()) != null) {
                    THREAD_POOL_EXECUTOR.execute(mActive);
                }
            }
    }
    

    这里用到了ArrayDeque对象,看名字就知道有点类似ArrayList的功能,没错它就是一个集合,excute里面添加任务到mTasks里面,然后在scheduleNext里面先是判断mActive是不是空的,可以看出来刚开始的时候,mTasks.poll()是空的对象,因此只有当调用了offer方法后,才能保证任务不是空的。因此可以看出来只有当mTasks有任务的时候,才能保证该任务被THREAD_POOL_EXECUTOR所执行,也保证了只有一个任务在执行,这个是SerialExecutor的职责,分析完了SerialExecutor是怎么工作的,下面到传进来的mFuturerun方法中看看了:

    public void run() {
            if (state != NEW ||
                !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
                return;
            try {
                //1.callable对象是传进来的mWorker对象
                Callable<V> c = callable;
                if (c != null && state == NEW) {
                    V result;
                    boolean ran;
                    try {
                        //2.调用了mWorker对象的call方法
                        result = c.call();
                        ran = true;
                    } catch (Throwable ex) {
                        result = null;
                        ran = false;
                        setException(ex);
                    }
                    if (ran)
                        set(result);
                }
            } finally {
                // runner must be non-null until state is settled to
                // prevent concurrent calls to run()
                runner = null;
                // state must be re-read after nulling runner to prevent
                // leaked interrupts
                int s = state;
                if (s >= INTERRUPTING)
                    handlePossibleCancellationInterrupt(s);
            }
    }
    

    看到注释1和注释2没,其实这里就是调用了AsyncTask类中的mWorker对象的call方法,再看下该方法:

    mWorker = new WorkerRunnable<Params, Result>() {
                public Result call() throws Exception {
                    mTaskInvoked.set(true);
                    Result result = null;
                    try {
                        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                        //noinspection unchecked
                        result = doInBackground(mParams);
                        Binder.flushPendingCommands();
                    } catch (Throwable tr) {
                        mCancelled.set(true);
                        throw tr;
                    } finally {
                        postResult(result);
                    }
                    return result;
                }
    };
    

    终于到了我们熟悉的影子了,doInBackground方法是在该处被触发的,在finally里面调用了postResult方法:

    private Result postResult(Result result) {
            @SuppressWarnings("unchecked")
            Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                    new AsyncTaskResult<Result>(this, result));
            message.sendToTarget();
            return result;
    }
    

    看到了没,这里有我们熟悉的handler的使用,并且发送的what值是MESSAGE_POST_RESULT,那咱们看下上面提到的InternalHandler:

    @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;
                }
    }
    

    此处当MESSAGE_POST_RESULT的时候,调用了AsyncTaskfinish方法:

    private void finish(Result result) {
            if (isCancelled()) {
                onCancelled(result);
            } else {
                onPostExecute(result);
            }
            mStatus = Status.FINISHED;
    }
    

    很熟悉了吧,这里直接调用了onPostExecute方法,并且把状态改成finish状态。在我们的demo中调用了publishProgress方法:

    protected final void publishProgress(Progress... values) {
            if (!isCancelled()) {
                getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                        new AsyncTaskResult<Progress>(this, values)).sendToTarget();
            }
    }
    

    也是通过handler发送了what= MESSAGE_POST_PROGRESS的消息,所以直接看到handler里面触发了AsyncTaskonProgressUpdate方法。整个过程基本是这样的,关于线程池没过多的分析,只针对它的excuse方法执行Runnable的run方法。

    总结

    AsyncTask首先会创建两个任务,一个是WorkerRunnable,一个是FutureTask,其中FutureTask是专门处理WorkerRunnable的,WorkerRunnable是真正处理子线程的任务。默认会创建一个SerialExecutor的线程池,以及ThreadPoolExecutor线程池,SerialExecutor的任务是将FutureTask惊醒包装放到自己的ArrayDeque队列里面,每次在取的时候,先要保证offer过了,才能取出该任务,并且该线程池保证了只有一个任务在执行,最后将ArrayDeque里面的Runnable交给了ThreadPoolExecutor线程池。所以说真正处理任务的还是ThreadPoolExecutor线程池。任务处理完了后,交给了Handler处理,Handler一共处理两种情况,一种是任务执行完了,一种是进度的改变,最后交给了onPostExecute方法。

    相关文章

      网友评论

        本文标题:AsyncTask源码整理一波

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