AsyncTask 源码详解

感谢鸿神大大提供的资料,本想直接转载的,后来发现有些东西弄的不是太清楚,所以就直接自己总结吧,有兴趣的可以自己看下鸿神的 blog,我这里就不讲 Executor 这块的知识了,我又没弄懂,讲出来也是直接 copy 过来的,没意思。

进入正题,可能现在大多数人还是在使用 Thread + Handler 来处理线程,或者直接线程池处理,其实我也是这样,毕竟理解起来简单,而且代码也容易写(相对于 AsyncTask),如果使用 AsyncTask,我们怎么做呢?

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        addAsyncTaskText()
    }

    fun addAsyncTaskText() {
        MyAsyncTaskText("aaaaaaaaaaa").execute("")
    }

    companion object {
        open class MyAsyncTaskText(var content: String) : AsyncTask<String, Int, String>() {

            /**
             * 准备工作  运行在主线程 
             */
            override fun onPreExecute() {
                super.onPreExecute()
            }

            /**
             * 运行在线程中 
             */
            override fun doInBackground(vararg params: String?): String {
                return content
            }

            /**
             * 运行在主线程 
             */
            override fun onProgressUpdate(vararg values: Int?) {
                super.onProgressUpdate(*values)
            }

            /**
             * 运行在主线程 返回值
             */
            override fun onPostExecute(result: String?) {
                super.onPostExecute(result)
            }
        }
    }

当时第一次用的时候,对于 onPreExecute、doInBackground、onProgressUpdate 和 onPostExecute 这四个方法,哪个运行在主线程可以更新 UI,哪个运行在子线程,不能做 UI 操作(请不要较真,谢谢),我只能死记硬背,时隔多年,正好闲着没事干,就准备研究下它的源码。

源码解析

既然有 AsyncTask 的执行方法,那我们先从它的执行方法来看,

   public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }

继续往下找,来看 executeOnExecutor 方法:

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

代码不多,但是涉及到了好多内容,我们一个一个的来解析,先来看下这个方法用啥用,根据官方注解来看下:

 通过这个方法我们可以自定义 AsyncTask 的执行方式,串行 or 并行,甚至可以采用自己的 Executor 为了实现并行,我们可以在外部这么用 AsyncTask:asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Params... params);  必须在UI线程调用此方法。

原来如此,这个方法可以用来串行或者并行,使用 AsyncTask 比较多的读者应该知道,在 Android 3.0 以前,AsyncTask 是并行的,而在 Android 3.0 以后包含 Android 3.0,AsyncTask 是串行的,那么难道真的没有办法在 Android 3.0 以后让 AsyncTask 并行开发吗,并不是,后面会讲解,如何实现让 AsyncTask 并行执行。

我们继续看 executeOnExecutor 源码,我们来看下第 15 行,先来说下这个状态,它是 AsyncTask 中的一个枚举类:

    public enum Status {
        /**
         * 任务等待执行
         */
        PENDING,
        /**
         * 任务已经执行
         */
        RUNNING,
        /**
         * 任务已经执行结束
         */
        FINISHED,
    }

我们看到第 17 行执行的是 onPreExecute 方法,而在 Android 3.0 以后到 Android 4.0.1 以前,executeOnExecutor 是执行在主线程的,而在 Android 4.0.1 以后,AsyncTask 是可以在子线程实例化的。

1. WorkerRunnable

继续往下看第 19 行,我们发现有一个 mWorker 出现了,那么它是什么呢,我们来看下 AsyncTask 的构造函数:

   public AsyncTask(@Nullable Looper 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;
            }
        };
    }

我们发现 AsyncTask 的构造函数实例化了一个 WorkerRunnable 类,并重写了 WorkerRunnable 的 call 方法,那么 WorkerRunnable 到底是个什么呢,我们继续往下看:

    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
        Params[] mParams;
    }

它只是用来接收我们传递给 AsyncTask 数据的一个类。

在构造方法中,在 call 方法中,调用了我们最熟悉的 doInBackground 方法,然后执行了 postResult 方法,来看下这个方法:

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

哈哈,熟悉的代码,忽然找到了亲切感,原来是这样,线程想更新 UI,始终摆脱不了 Handler 啊,那么我们就来找到这个 Handler:

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

我们来看下 switch 这段代码,第一个 case 的值正好对应 postResult 方法中发送的值啊,那就来看下 finish 方法呗,

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

好嘛,这里进行了一次判断,是否被取消,取消调用 onCancelled,否则调用 onPostExecute,还记得 AsyncTask 构造中 try ... catch 中抛出的异常吗?

  mCancelled.set(true);

通过 finish 方法,我们知道它是运行在主线程的,并且里边调用了 onPostExecute,也就说明了 onPostExecute 运行在主线程了。最后把状态设置成 FINISHED 状态。

2. FutureTask

看完了 WorkerRunnable,我们继续来看下一个重点,FutureTask,继续来看 AsyncTask 的构造:

    public AsyncTask(@Nullable Looper callbackLooper) {
        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);
                }
            }
        };
    }

只执行了一个方法 postResultIfNotInvoked,那么它到底有什么用呢?其实啊,postResultIfNotInvoked 的中的那个 get 方法获取的就是 mWorker 中的那个 Result 值,来看下 postResultIfNotInvoked 方法:

    private void postResultIfNotInvoked(Result result) {
        final boolean wasTaskInvoked = mTaskInvoked.get();
        if (!wasTaskInvoked) {
            postResult(result);
        }
    }

如果 wasTaskInvoked 为 false,则执行 postResult,但是在 AsyncTask 的构造中,wasTaskInvoked 就已经被设置为了 true,

public AsyncTask(@Nullable Looper callbackLooper) {
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);
                Result result = null;
                ...
                return result;
            }
        };
    }

所以呢,这里的 postResult 一般不会执行,具体什么时候执行呢,我在研究下。

还有一个方法没有说到,这里来说下,在 doInBackground 中执行了我们需要讲解的方法,onProgressUpdate 方法:

    @Override
    protected ReusableBitmap doInBackground(Void... params) {
        // enqueue the 'onDecodeBegin' signal on the main thread
        publishProgress();

        return decode();
    }

我们来看下 publishProgress 方法:

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

还记得我们那个 Handler 的 switch 吗?我们只说了第一个 case ,我们来看第二个 case:

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

在第二个 case 中,执行了我们可以重写的 onProgressUpdate 方法,这也是为什么他可以做进度条的原因了。

并行执行

在上边我给出的例子只是串行执行的,那么在 Android 3.0 及以后怎么并行执行呢,其实呢,也很简单,我们只需要调用 AsyncTask 的 executeOnExecutor 方法而不是 execute 就可以了啊。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        addAsyncTaskText()
    }

    fun addAsyncTaskText() {
        MyAsyncTaskText("aaaaaaaaaaa").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"")
    }

    companion object {
        open class MyAsyncTaskText(var content: String) : AsyncTask<String, Int, String>() {

            /**
             * 准备工作  运行在主线程
             */
            override fun onPreExecute() {
                super.onPreExecute()
            }

            /**
             * 运行在线程中
             */
            override fun doInBackground(vararg params: String?): String {
                return content
            }

            /**
             * 运行在主线程
             */
            override fun onProgressUpdate(vararg values: Int?) {
                super.onProgressUpdate(*values)
            }

            /**
             * 运行在主线程 返回值
             */
            override fun onPostExecute(result: String?) {
                super.onPostExecute(result)
            }
        }
    }

好了,关于 AsyncTask 的源码已经分析完了,有错的地方请指出,谢谢!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值