美文网首页Android开发之旅
AsyncTask源码学习笔记一

AsyncTask源码学习笔记一

作者: 拿头撞鸡 | 来源:发表于2016-05-30 11:35 被阅读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源码学习笔记二

    相关文章

      网友评论

        本文标题:AsyncTask源码学习笔记一

        本文链接:https://www.haomeiwen.com/subject/imaqdttx.html