Android开发之旅

AsyncTask源码学习笔记一

2016-05-30  本文已影响50人  拿头撞鸡

本文AsyncTask源码sdk版本为23,资料来源参考《Android开发艺术》

一、为什么使用AsyncTask

避免了每次开启一个线程thread,都需要写一个handler去通知主线程更新,就是Google帮大家封装了thread和handler。

AsyncTask并不适合进行特别耗时的后台任务,对于特别耗时的任务来说,建议使用线程池。

这是主席在开发艺术中的原话,但AsyncTask中的实现,在sdk23中是使用了线程池的,都是使用线程池,那在AsyncTask中做耗时任务,与自己单独使用线程池有什么区别,这里略有疑问。

二、内部实现

首先,这玩意是个抽象类。所以你必须写一个自己的task去继承AsyncTask,并重写几个核心方法。这点可以很好理解为,整体的内部逻辑实现好了,关键的那几个步骤,你自己去重写,你想咋干咋干。根据这个,AsyncTask使用了模板模式,具体实现方法由子类重写。

那看看AsyncTask需要重写哪几个核心方法。

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

protected void onPreExecute() {}

protected void onPostExecute(Resultresult) {}

protected voidonProgressUpdate(Progress... values) {}

protected void onCancelled() {}

其中doInBackground方法为抽象方法是必须要重写的,这是肯定的,就指着这方法在线程中执行。其他的protected方法也是希望你去重写的,注意一点,方法体内都为空,更说明了使用了模板模式。

整体实现逻辑流程

先整体看看大致实现,全局掌控,心里有底不虚。

先要有两个概念,callable 接口和future类,这是带返回值的线程使用。毕竟AsncTask在任务执行完后要可以提供返回值。

我们在使用AsyncTask时都是自己写一个类继承它,然后实例一个对象,然后执行execute()方法。

那我们就从它的构造方法看起


public AsyncTask() {

      mWorker=new WorkerRunnable() {

            public Result call() throws Exception {

                     mTaskInvoked.set(true);

                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

                   //noinspection unchecked

                   Result result = doInBackground(mParams);

                  Binder.flushPendingCommands();

                  return postResult(result);

                }

        };

    mFuture=new FutureTask(mWorker) {

        @Override

        protected voiddone() {

        //.......省略代码

         }

     };

}

诶~! 有一个很眼熟的方法 有木有,doInBackground,看来我们自己实现的doInBackground就在这里执行了。WorkerRunnabler实现了Callable接口,所以线程执行就在这里了。那就还需要一个FutureTask了,下面mFuture就是个FutureTask,看来AsyncTask就是靠这两个API;

好接下来看execute方法。


public final  AsyncTask execute(Params... params) {

   return   executeOnExecutor(sDefaultExecutor, params);

}

看来执行放在了executeOnExecutor(Executor exec,Params... params)中。两个参数一个是Executor,看来是会用到线程池,一个params参数


public finalAsyncTask executeOnExecutor(Executor exec,Params... params) {

     //......省略

   mStatus= Status.RUNNING;

   onPreExecute();

  mWorker.mParams= params;

  exec.execute(mFuture);

  return this;

}

又看到了熟悉的函数onPreExecute,在任务执行前,先执行onPreExeute方法。将参数params赋值给mWorker的mParams,也就是构造其中的doInBackground的参数就是从这里传过去的。

好了执行异步任务的逻辑就这么基本走完了。那线程结束后是如何通知主线程的呢,那就要用到handler了。

我们在回过头看看构造器中WorkRunnable的返回值是什么 返回了一个方法postResult(result)

private Result postResult(Result result) {

    Message message =getHandler().obtainMessage(MESSAGE_POST_RESULT,

                newAsyncTaskResult(this, result));

    message.sendToTarget();

   return result;

}

看来postResult中通过使用了handler发送消息给主线程,然后在通过handler的handlerMessage方法处理传递来的消息。

好了 AsyncTask的整体实现逻辑也就到此了。下一篇笔记将继续深入学习AsyncTask是如何通过handler与线程交互的AsyncTask源码学习笔记二

上一篇下一篇

猜你喜欢

热点阅读