不是大牛,也能分析 AsyncTask 源码流程

284 阅读3分钟

这是我参与更文挑战的第6天,活动详情查看: 更文挑战 这几天在看一些教程,说到了源码分析的方法,其中之一就是不要纠结于每一行代码到底代表什么,而是要先搞清楚主要流程并学习里面的设计思想。并带着分析了一下 AsyncTask 的源码。分析之后确实感觉受益匪浅,虽然里面一些线程的知识并不了解,但是对整体设计和流程有了一个新的认识。所以为了分享下学到的东西,就记录一遍,希望大家也能有所收获。

注意 AsyncTask 在 SDK30 及以上已经被弃用,在开发中并不推荐使用了。

首先,新建一个 AsyncTask 后,实现具体的方法,调用 execute() 方法执行。

之后会调用到这里,可以看到 AsyncTask 是不能够重复调用的,而且 onPreExecute() 会首先调用。

    // 1.运行状态初始值是 Status.PENDING
    private volatile Status mStatus = Status.PENDING;   

    @MainThread
    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
            Params... params) {
        if (mStatus != Status.PENDING) {
            switch (mStatus) {
                case RUNNING:
                    // 2.如果正在执行,则报错
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task is already running.");
                case FINISHED:
                    // 3.如果已经执行结束,则报错,这里解释了 AsyncTask 不可以重复执行
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task has already been executed "
                            + "(a task can be executed only once)");
            }
        }
        // 4.修改状态
        mStatus = Status.RUNNING;
        // 5.调用 onPreExecute() 方法
        onPreExecute();

        mWorker.mParams = params;
        // 6.在线程池中执行 mFuture
        exec.execute(mFuture);

        return this;
    }

现在来看一下 exec.execute(mFuture); 这里面涉及到线程相关的知识就暂时不讨论,我们只看整体的流程。搜索一下可知 mFuture 是在构造方法中初始化的,代码如下。

    public AsyncTask(@Nullable Looper callbackLooper) {
        // 1.获取 handler
        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
            ? getMainHandler()
            : new Handler(callbackLooper);

        // 4.mWorker 和 mFuture 定义了线程相关的操作,具体的实现原理不太清楚,暂时不看,只看里面的
        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
                    // 5.执行了 doInBackground 方法,这里已经是在子线程了
                    result = doInBackground(mParams);
                    Binder.flushPendingCommands();
                } catch (Throwable tr) {
                    mCancelled.set(true);
                    throw tr;
                } finally {
                    // 6.将执行结果发送出去
                    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);
                }
            }
        };
    }

	// 2.这里提供一个 Handler 单例
    private static Handler getMainHandler() {
        synchronized (AsyncTask.class) {
            if (sHandler == null) {
                sHandler = new InternalHandler(Looper.getMainLooper());
            }
            return sHandler;
        }
    }

	// 3.可以看到实现了 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;
            }
        }
    }

	// 7.通过 message 发送执行结果,发送后会回调到上方注释 3 处。
    private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult<Result>(this, result));
        message.sendToTarget();
        return result;
    }

到这里基本执行流程就完成了,还有一个更新状态的方法其实也是通过发送 message 实现的。

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

简单分析下来,整体流程有了个认识,当然这里面涉及到的一些线程的相关知识还不是了解的很多,但是这并不妨碍我们。

好了文章到这里就结束了,希望对大家有所帮助。