AsyncTask源码解读

1、AsyncTask是一个抽象类,其中重要的属性有以下几个:
THREAD_POOL_EXECUTOR:一个Executor对象,AsyncTask内部也是定义了一个线程池对象,真正的执行任务的地方
mWorker :定义了在子线程中执行的回调
SERIAL_EXECUTOR:一个有序的Executor对象,内部存储了一个任务的队列,串行执行Runnable
mFuture:作为一个线程池处理的任务对象,能够提供结果的回调
sHandler:作为子线程到主线程之间的数据通信

2、下面对常见用法AsyncTask.execute()做代码跟踪
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);
                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);
            }
        }
    };
}

上面构造方法中,定义了mHandler ,mWorker对象和mFuture对象,mHandler 主要用来处理多线程中传递数据的问题。

execute()前部分调用的流程解析

AsyncTask.execute()--->AsyncTask.executeOnExecutor()--->AsyncTask.onPreExecute()--->sDefaultExecutor.execute(mFuture)

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

继续调用executeOnExecutor(),这里传入了参数sDefaultExecutor,系统默认设置值为SerialExecutor对象,SerialExecutor后面分析。

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

上面调用了onPreExecute();这个就是留给用户调用的方法,继续调用exec.execute(mFuture);exec是前面传入的SerialExecutor对象;mFuture是构造方法中定义的Future对象。

下面接着看SerialExecutor中的execute()

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 {
                       r.run();
                   } finally {
                       scheduleNext();
                   }
               }
           });
           if (mActive == null) {
               scheduleNext();
           }
       }

       protected synchronized void scheduleNext() {
           if ((mActive = mTasks.poll()) != null) {
               THREAD_POOL_EXECUTOR.execute(mActive);
           }
       }
   }

在SerialExecutor 中定义了一个ArrayDeque对象,ArrayDeque是双端队列,具有先进先出或后进先出的特点,底层使用的是数组存储元素,这里的元素是Runnable对象。前面调用execute()方法,传入的是mFuture对象,先创建一个Runnable对象,存入到双端队列mTasks 中,第一次mActive 为null,调用scheduleNext(),再将mTasks中存入的元素取出来赋值给的mActive 并调用线程池THREAD_POOL_EXECUTOR进行执行。赋值给mActive 是为了不让多任务情况下同步执行,这里就决定了不能同步多任务执行的情况。

THREAD_POOL_EXECUTOR是一个线程池对象:

 public static final Executor THREAD_POOL_EXECUTOR;

    static {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory);
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        THREAD_POOL_EXECUTOR = threadPoolExecutor;
    }

线程执行任务会调用mFuture的run()方法,mFuture是FutureTask对象,实现了Runnable, Future接口

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

这里重点调用 result = c.call();c对象是FutureTask的构造方法中进行的赋值,传入的是AsyncTask构造方法中的mWorker对象,继续调用mWorker的call方法,先跳过mWorker的执行call(),将执行的结果传入set(result),setf方法会将结果保存在成员变量outcome中留待后面取出;
set(result)---> finishCompletion();--->done();
finishCompletion()方法中会删除所有的等待的线程。done()方法是AsyncTask构造方法mFuture定义复写父类的方法。
done()--->postResultIfNotInvoked(get());--->postResult(result);
get()方法会取得FutureTask的run()执行的结果outcome。

postResult(result);这一步已经是取得了子线程执行的结果,下一步需要将结果传递给主线程,系统采用的是handler的方法进行数据的传递。

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

1)getHandler()取得是mHandler,是在AsyncTask的构造方法中定义的,mHandler由构造方法中传入的参数决定是属于哪一个线程的循环器,默认使用的是主线程的循环器,所以mHandler默认是属于子线程。

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

2)对结果进行了封装,封装结果为AsyncTaskResult对象,并进行了传递。

现在是主线程中处理最后的结果

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

这里按照不同情况处理最后的结果调用了AsyncTask的finish方法或者onProgressUpdate方法。
到这里就已经结束了整体的大概流程的分析。现在前面还留有一个mWork的call的方法调用,在AsyncTask的构造方法中

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(mParams)方法,这就是留给用户自己实现的方法,在子线程中处理相关事项。并调用了 postResult(result);通知主线程。

至于MESSAGE_POST_PROGRESS的处理情况,一般是用户在doInBackground中主动去调用publishProgress(Progress... values)方法才可以。

总结:大概的流程分析就这样,具体的细节还得自己去分析,总体上AsyncTask使用了线程池开启子线程处理后台任务,然后使用了Handler进行子线程和主线程之间的数据传递问题。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容