AsyncTask 源码流程简析

参考链接:
https://blog.csdn.net/lmj623565791/article/details/38614699

AsyncTask的几个重要函数和参数

AsyncTask是一个抽象类,我们通常会自定义一个内部类继承AsyncTask,然后实现它的几个重要方法。
AsyncTask的执行过程如下:
通过自定义AsyncTask实例执行execute方法启动AsyncTask来进行数据库查询,访问网络等耗时操作。
1 执行AsyncTask的onPreExecute方法,该方法执行在主线程,用于task执行前一些初始化操作。
2 紧接着doInBackground被执行,用于处理后台耗时操作,该方法不在主线程执行。
在doInBackground中可以通过publishProgress通知主线程更新UI(比如显示下载进度等等)
3 publishProgress会导致onProgressUpdate回调,onProgressUpdate执行在主线程,可以在此更新UI
4 线程执行完毕后onPostExecute会被执行。

另外值得注意的是,继承AsyncTask时会需要指定Params, Progress, Result三个泛型参数。
这三个参数分别代表
1 Params:传入Task的参数,(即excute的参数),比如访问网络的uri,会通过doInBackground的参数传给子线程
2 Progress:任务执行进度,通常指定为Integer类型,可以通过在doInBackground中调用publishProgress来通知onProgressUpdate更新UI
3 Result:doInBackground的返回值,会返回给onPostExecute。

简单示例

public class MainActivity extends Activity {
    Button btn;
    ImageView iv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn = (Button) findViewById(R.id.test);
        btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                ImageLoadTask itask = new ImageLoadTask();
                itask.execute("https://www.baidu.com/img/bd_logo1.png");
            }
        });
        iv = (ImageView) findViewById(R.id.iv);

    }

    class ImageLoadTask extends AsyncTask<String, Integer, Bitmap> {

        @Override
        protected void onPreExecute() {
            // TODO Auto-generated method stub
            super.onPreExecute();
        }

        @Override
        protected Bitmap doInBackground(String... arg0) {
            // TODO Auto-generated method stub
            Log.d("chj", "doInBackground arg0" + arg0[0]);
            Bitmap bitmap = null;
            URLConnection conn = null;
            InputStream is = null;
            try {
                URL url = new URL(arg0[0]);
                conn = url.openConnection();
                is = conn.getInputStream();
                BufferedInputStream bis = new BufferedInputStream(is);
                bitmap = BitmapFactory.decodeStream(bis);
                is.close();
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return bitmap;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            // TODO Auto-generated method stub
            super.onProgressUpdate(values);
        }

        protected void onPostExecute(Bitmap result) {
            Log.d("chj", "onPostExecute");
            iv.setImageBitmap(result);
        }
    }

}

AsyncTask源码简析

AsyncTask起始于AsyncTask的execute方法,我们也以此为入口,了解源码的执行过程

    @MainThread
    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }
    @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;
    }

我们看到AsyncTask执行前进行了状态判断,状态有三种 空闲 运行中 结束状态。AsyncTask的状态初始化为空闲状态,之后不会再变成空闲状态了,也就是说,一个AsyncTask只能执行一次,之后就会因为状态错误抛出异常。如果状态正确,那么,就记录当前状态为运行状态,下面我们看到了第一个熟悉的函数onPreExecute,点进去看看:

    @MainThread
    protected void onPreExecute() {
    }

空实现,等着我们实现呢,另外注意到,这个方法是运行在主线程的。接着往下看,有两个变量mWorker和mFuture,定义如下

    private final WorkerRunnable<Params, Result> mWorker;
    private final FutureTask<Result> mFuture;

mWorker是一个实现了Callable的WorkerRunnable,记住他实现了Callable,后面会用到。FutureTask是Java自带类型,我们暂且知道他是个异步Task即可。

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

他们的初始化是在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);
                }
            }
        };
    }

我们看到mWorker实现了call方法,并将自己作为参数传给了mFuture,mFuture重写了done方法。这里具体实现我们可以后面再看,这里只是初始化了一下,并没有实际调用方法。接着往下看,exec.execute(mFuture);中exec是什么呢?往前追溯,不难发现,是

executeOnExecutor(sDefaultExecutor, params);

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

原来他是一个穿行线程池,初始情况下mActive == null必然成立,执行scheduleNext方法,从队列取出一个Task,交给THREAD_POOL_EXECUTOR执行。我们可以将sDefaultExecutor理解为存放Task的线程池。那么THREAD_POOL_EXECUTOR又是什么,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;
    }

我们看到他是ThreadPoolExecutor,也就是说,他也是一个线程池,他的常量定义如下,可以看出,THREAD_POOL_EXECUTOR的核心和非核心线程都是30s超时,缓存队列大小为128。

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    // We want at least 2 threads and at most 4 threads in the core pool,
    // preferring to have 1 less than the CPU count to avoid saturating
    // the CPU with background work
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE_SECONDS = 30;

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
        }
    };

    private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(128);

好了,执行者的情况我们了解了。

exec.execute(mFuture);

短短一句话,内容其实很多,从串型线程池取出task交给执行者线程池THREAD_POOL_EXECUTOR来执行,当然执行对象是mFuture,那么我们看看mFuture也就是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();
                    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);
        }
    }

注意到这里调用了Callable的call方法,还记得之前我们在AsyncTask构造函数那边说的嘛,mWork将自己作为参数传给了mFuture,而mWork是一个实现Callable的对象。这里调用的call方法其实是mWorker的call方法。下面看下我们之前没有看的call方法的具体实现

        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的第二个方法doInBackground,方法定义如下

    @WorkerThread
    protected abstract Result doInBackground(Params... params);

可以看到这个方法是执行在工作线程的。如果没有异常会调用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仅仅是发了个message,AsyncTaskResult是什么呢

    private static class AsyncTaskResult<Data> {
        final AsyncTask mTask;
        final Data[] mData;

        AsyncTaskResult(AsyncTask task, Data... data) {
            mTask = task;
            mData = data;
        }
    }

从上述代码看出,AsyncTaskResult仅仅是个保存作用的数据结构,存储了当前task和result。熟悉handler的同学应该会立马想到这个消息发出来了,必定有处理者,那么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;
            }
        }
    }

我们看到之前发送的MESSAGE_POST_RESULT消息,此时会调用finish方法,finish方法定义如下

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

分析上述代码可以看到,如果Task取消了会回调onCancelled方法否则,回调onPostExecute方法。我们看到了AsyncTask第三个常见方法onPostExecute。

    @MainThread
    protected void onPostExecute(Result result) {
    }

可以看到,这个方法执行在主线程。到这里,AsyncTask 就执行完毕了。有心者会发现除了MESSAGE_POST_RESULT消息还有个MESSAGE_POST_PROGRESS呢,这个消息是何时发送的呢?追踪代码,我们看到了第四个AsyncTask常见方法publishProgress。调用publishProgress其实就是发送了MESSAGE_POST_PROGRESS消息。

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

以上为参考网上一些资料,做的总结,如有错误,请帮忙指出。

猜你喜欢

转载自blog.csdn.net/u011109881/article/details/79943321