从源码分析AsyncTask执行流程和原理

版权声明:本文出自wdmzszly的博客,转载必须注明出处。 https://blog.csdn.net/wdmzszly/article/details/82857494

本篇文章将从大体上分析AsyncTask的原理,不会涉及过多的细节。AsyncTask现在已经不再流行了,但作为学习还是要了解下。

使用方法

下面是AsyncTask一般的使用场景,相信使用过AsyncTask的人都不会觉得陌生

class MyAsyncTask extends AsyncTask<Void,Void,Void>{
​
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            //做初始化操作
        }
​
        @Override
        protected Void doInBackground(Void... voids) {
            boolean tag = true;
            while(tag){
                //耗时操作
                publishProgress();
            }
            return null;
        }
​
        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);
        }
​
        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            //处理执行的结果
        }
    }
​
    MyAsyncTask task = new MyAsyncTask();
task.execute();

源码分析

下面从execute方法开始分析

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

execute内部调用了executeOnExecutor方法,并且传了一个sDefaultExecutor,sDefaultExecutor是什么呢?

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
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() {//对参数r进一步封装
            public void run() {
                try {
                    r.run();
                } finally {
                    //执行完一个任务之后,继续取出另一个任务执行
                    scheduleNext();
                }
            }
        });
        if (mActive == null) {
            //如果当前没有正在执行的任务,则从mTasks队列取出一个任务去执行
            scheduleNext();
        }
    }
​
    protected synchronized void scheduleNext() {
        if ((mActive = mTasks.poll()) != null) {
            //THREAD_POOL_EXECUTOR才是正在执行任务的Executor
            THREAD_POOL_EXECUTOR.execute(mActive);
        }
    }
}

可以看到sDefaultExecutor是SerialExecutor类的对象,SerialExecutor实现了Excutor接口,并重写了execute方法。SerialExecutor里面有个ArrayDeque对象MTasks,在execute方法里面,调用了mTasks的offer方法将一个Runnable对象加入队列中。注意,并不是直接把参数Runnable对象加入,而是新new了一个Runnable,然后在新new的Runnable对象的run方法里面,调用了传递参数Runnable对象的run方法,最后还调用了scheduleNext()方法。通过这种逻辑实现了串行执行任务,而不是并行执行。在scheduleNext方法里面,调用了THREAD_POOL_EXECUTOR.execute(mActive);可以看到THREAD_POOL_EXECUTOR才是真正执行任务的Executor,而sDefaultExecutor只是用于做串行处理。

我们接着看回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:
                //一个task只能执行一次
                throw new IllegalStateException("Cannot execute task:"
                        + " the task has already been executed "
                        + "(a task can be executed only once)");
        }
    }
​
    mStatus = Status.RUNNING;
​
    onPreExecute();//先调用onPreExceute方法。所以execute()要在主线程调用才能保证                   
                   //onPreExecute()在主线程执行
​
    mWorker.mParams = params;//保存接收到的参数,到时传给doInBackground()方法
    exec.execute(mFuture);//执行mFuture
​
    return this;
}

可以看到executeOnExecutor方法里面先调用了onPreExecute()方法,最终调用exec.execute(mFuture)开始执行任务。mFuture对象是在构造方法里面创建的。

AsyncTask的构造方法

/**
 * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
 *
 * @hide
 */
public AsyncTask(@Nullable Looper callbackLooper) {
    //创建handler
    mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
        ? getMainHandler()
        : new Handler(callbackLooper);
​
    //创建WorkerRunnable对象
    mWorker = new WorkerRunnable<Params, Result>() {
        public Result call() throws Exception {
            mTaskInvoked.set(true);
            Result result = null;
            try {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //doInBackground方法运行在子线程
                result = doInBackground(mParams);
                Binder.flushPendingCommands();
            } catch (Throwable tr) {
                mCancelled.set(true);
                throw tr;
            } finally {
                //运行结果发送出去
                postResult(result);
            }
            return result;
        }
    };
​
    //创建FutureTask对象
    //mWorker的call方法在FutureTask的run方法里面执行
    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);
            }
        }
    };
}

构造方法里面创建了mFuture对象,并传入了mWorker对象,FutureTask可以看做是一个可以取到执行结果的Runnable。mWorker是WorkerRunnable的对象,WorkerRunnable是实现了Callable接口的子类,只有call方法,call方法会在mFuture的run方法中被调用。call方法里面得到doInBackground返回的结果,然后传给了postResult()方法。

我们看下postResult()方法

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

postResult()方法封装了result,然后通过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://接受publishProgress方法发送过来的结果
                result.mTask.onProgressUpdate(result.mData);
                break;
        }
    }
}

handlerMessage调用了finish()方法

private void finish(Result result) {
    if (isCancelled()) {
        onCancelled(result);
    } else {
        onPostExecute(result);//onPostExecute()方法在这里调用了
    }
    mStatus = Status.FINISHED;
}

这里我们看到了熟悉的onPostExecute()回调方法。如果该task是取消的就会回调onCancelled()方法。

在handleMessage方法里面还有另一个case:MESSAGE_POST_PROGRESS,这种情况调用了我们熟悉的onProgressUpdate()方法。我们重写doInBackground()方法在里面调用publishProgress()方法就会有了onProgressUpdate()方法回调。

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

总结

AsyncTask实际上是封装了两个线程池THREAD_POOL_EXECUTOR、sDefaultExecutor和一个Handler。sDefaultExecutor做串行执行的逻辑,THREAD_POOL_EXECUTOR是真正执行任务的线程池,Handler是用于线程的切换。

注意点

1、由于execute()方法直接调用了onPreExecute()方法,而onPreExecute()是需要在主线程的,所以execute()方法 需要在主线程操作

2、由于AsyncTask默认是串行执行任务的,所以AsyncTask不适合做太过于耗时的操作

3、executeOnExecutor()方法是public的,通过指定特定的Executor可以实现并行

猜你喜欢

转载自blog.csdn.net/wdmzszly/article/details/82857494