AsyncTask内部原理

版权声明:该博客为博主原创,转载请标明出处! https://blog.csdn.net/DJH2717/article/details/81263482

AsyncTask 是一个封装了 ThreadPoolExecutor 和 Handler 机制的抽象类,其作用是方便开发者进行多个异步任务时无需手动在每个线程中都采用 Handler 机制来通知 UI 线程进行操作, 从而简化了多个异步任务与 UI 线程的通信的情况.


使用 AsyncTask :

  1.  在主线程中创建一个 AsyncTask 自定义子类的实例对象.
  2. 然后调用 execute 方法.

下面从这两个过程,分别从源码的角度探索 AsyncTask 的执行流程和内部原理:

1. new AsyncTask()

源码:

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); // 注意此处调用了 doInBackground
                    Binder.flushPendingCommands();
                } catch (Throwable tr) {
                    mCancelled.set(true);
                    throw tr;
                } finally {
                    postResult(result);
                }
                return result;
            }
        };

        mFuture = new FutureTask<Result>(mWorker) { // 注意此处传入了 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);
                }
            }
        };
    }

其中 WorkerRunnable 是 AsyncTask 一个内部类,源码如下:

private static abstract class WorkerRunnable<Params, Result> 
                                   implements Callable<Result> { // 注意实现了 Callable接口
        Params[] mParams;
    }

2. execute

源码如下:

    @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(); // 注意此处调用了 onPreExecute

        mWorker.mParams = params; // 注意此处把传入的 params 赋值给了 mParams
        exec.execute(mFuture); // 然后调用了 exec 的 execute 方法, exec 实际上是 ThreadPoolExecutor 的实例对象,只是进行一系列的骚操作,然后转型成了 Executor 接口变量

        return this;
    }

  在 Execute 方法内部, 会把 mFuture(FutureTask实例) 对象传递给了 exec.execute 方法, 所以最终会在 ThreadPoolExecutor 的工作线程中调用传入的 mFuture 对象的 run 方法.

  然后之前在构建 mFuture 实例对象时,传入了 mWorker(实现了Callable接口)  对象,然后在 mFuture 的 run 方法内部会调用到 mWorker 实现的 call 方法, 源码如下(FutureTask 的 run 方法):

public void run() {
        if (state != NEW ||
            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
            return;
        try { 
            Callable<V> c = callable; // 注意此处的赋值
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call(); // 调用了 call 方法,也就是 mWorker 的 call 方法,而 mWorker 的 call 方法会调用我们自己实现的 doInBackground 方法
                    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);
        }

   经过如上的这些步骤, AsyncTask 最终把我们的实现的 doInBackground 方法包装在一个 call (mWorker) 方法内部.

  然后传入给了一个 FutureTask 实例对象, 在调用 execute 方法时, AsyncTask 把这个 FutureTask 实例对象用 ThreadPoolExecutor 的 execute 进行执行, 从而实现了 doInBackgroun 方法得以在子线程中执行.

  然后在此过程中如果开发者在 doInBackground 方法内部调用了 publishProgress 方法, 则会使用在 AsyncTask 的构造方法中创建的 Handler 对象发送消息到 UI 线程, Handler 处理消息时会调用 onProgressUpdate 方法,所以这也是为什么 AsyncTask 必须要在 UI 线程实例化的原因了.

  最后在 doInBackground 方法执行完成后, 同样也是用 handler 发送消息到主线程, 然后 handler 在处理消息时会调用 onPostExecute 方法.

更多细节,有待后续研究.....

猜你喜欢

转载自blog.csdn.net/DJH2717/article/details/81263482
今日推荐