欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新

Android源码分析之AsyncTask

来源: 开发者 投稿于  被查看 25623 次 评论:145

Android源码分析之AsyncTask


  AsyncTask相信从事Android开发的同学都不陌生,基本都应该用到了,和以前一样我们还是先来看看此类的summary。AsyncTask

可以确保更合理、容易的使用UI线程。这个类是设计用来执行一个后台操作然后将结果发布到UI线程,但却使你不必直接操作Thread

和Handler(其实内部已经为你封装好了而已)。AsyncTask是围绕Thread和Handler而设计的一个Helper类,它的目标并不是提供

一个generic的Thread框架。AsyncTask的理想使用情况是针对比较短暂的操作(比如至多几秒钟的那种),所以说如果你需要Thread

长时间的运行,那么强烈建议你使用java.util.concurrent包里提供的各种API,比如Executor、ThreadPoolExecutor和FutureTask。

  接下来我们看看AsyncTask的各个字段,字段比较多:

    CPU_COUNT =    CORE_POOL_SIZE = CPU_COUNT + 1    MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1    KEEP_ALIVE = 1   ThreadFactory sThreadFactory =   AtomicInteger mCount =  AtomicInteger(1  Thread(r, "AsyncTask #" +   BlockingQueue<Runnable> sPoolWorkQueue =
             LinkedBlockingQueue<Runnable>(128
      = 

这些字段基本都能望文生义,主要是为了创建最下面的ThreadPoolExecutor(有时间的话我会分析下它的源码),需要留意的

可能就算是这里CORE_POOL_SIZE的取值,为cpu的数目加1,这样做可以刚好保持cpu忙碌,最大限度的提高cpu利用率。

ThreadPoolExecutor是一种特殊的Executor,其runnable的执行是在线程池里并行完成的。

  下面我们看看另一种特殊的Executor,串行Executor,代码如下:


       Executor SERIAL_EXECUTOR =    SerialExecutor  ArrayDeque<Runnable> mTasks =  ArrayDeque<Runnable>   execute(  (mActive ==    ((mActive = mTasks.poll()) != 

这里的重点是一个Deque实现ArrayDeque,可以看出offer方法往deque尾部添加一个新的Runnable,这个Runnable比较特殊,它做的事情是执行

当前的AsyncTask,最后安排下一个AsyncTask执行(全局的AsyncTask都会在这里排队),这样就实现了AsyncTask的串行执行(执行顺序是FIFO)。

这里要注意的是即使是串行化的执行还是delegate给了同一个(和并行执行每个AsyncTask相比)THREAD_POOL_EXECUTOR。

  下面是剩下的一堆字段:

    MESSAGE_POST_RESULT = 0x1    MESSAGE_POST_PROGRESS = 0x2   InternalHandler sHandler =    Executor sDefaultExecutor =  WorkerRunnable<Params, Result>  FutureTask<Result>  Status mStatus =  AtomicBoolean mCancelled =   AtomicBoolean mTaskInvoked =  AtomicBoolean();

MESSAGE_xxx之类的是post message用到的what字段;

sHandler是和UI线程相关(所以你应该在UI线程中创建AsyncTask,因为默认其他线程一般没有与之关联的Looper)的处理后台线程

post message的Handler,具体代码稍后分析;

sDefaultExecutor表示默认的Executor,即串行执行的;

mWorker是一个抽象类实现了Callable<Result>接口,还有个Params类型的数组字段mParams;

mFuture表示一个可取消的异步操作,这里指的就是mWorker;

mStatus表示task执行过程中的状态,剩下的是2个原子boolean变量,用来做标记使用;

  表示task的当前状态的enum,如下:


     

  接下来来看一个关键部分,ctor代码如下:


    =  WorkerRunnable<Params, Result> Result call() 
                =  FutureTask<Result>   RuntimeException("An error occured while executing doInBackground()"

构造器说白了就是分别初始化mWorker和mFuture;mWorker表示可以返回结果的runnable,在其call方法中主要做3件事:

1. 设置task为invoked;

2. 设置线程优先级为BACKGOURND级别;

3. 调用doInBackground(mParams),并将结果发布到UI线程;

mFuture重写了其protected的done方法,在其内调用get方法来获取计算结果,get方法可能抛出3种异常,这里分别处理之;

如果执行正常即没任何异常的话,则再次将结果post到UI线程如果还没post过的话;

  接下来就来看看将background线程的结果/进度post到UI线程的相关方法:

    wasTaskInvoked = (!"unchecked"= AsyncTaskResult<Result>(
       (! AsyncTaskResult<Progress>(

前者只在task没被invoked的时候post,postResult的具体实现是obtain一个Message(将result包装在Message中),发送给sHandler处理;

publishProgress可以将后台线程的进度周期性的汇报给UI线程,可以用来更新UI显示,其实现也都是发送Message到sHandler,但是是在任务

没被取消的前提下。

  接下来看几个客户端可能需要override的方法,如下:


     
     "UnusedDeclaration" "UnusedDeclaration" "UnusedParameters" 
     
      

这些方法你可以根据自己的需要重写其中某些,一般doInBackground都会被重写,因为这是你使用AsyncTask的目的,你的后台操作就发生

在这里面;其他几个onXXX之类的方法都发生在UI线程中,算是种callback机制,用来通知UI线程什么事情发生了。其他要注意的就是仔细阅读

下方法的doc,每个都有清晰的说明。

  下来接着看下public的cancel和get方法,


       cancel(
      Result get() 
      Result get( timeout, TimeUnit unit) 

这些方法没什么多说的,都是delegate给了mFuture,主要就是多看看方法的doc。

  接下来看看关键的executeXXX方法,代码如下:


      AsyncTask<Params, Progress, Result>
      AsyncTask<Params, Progress, Result> (mStatus !=  IllegalStateException("Cannot execute task:"
                            + " the task is already running."  IllegalStateException("Cannot execute task:"
                            + " the task has already been executed "
                            + "(a task can be executed only once)"== 
      

从上面的代码可以看出如果你不指定Executor,则默认的串行化Executor会被使用,当然如果你愿意也可以提供自己的Executor,

比如AsyncTask.THREAD_POOL_EXECUTOR。executeOnExecutor方法在执行前会做一些状态检测,没执行前应该处于PENDING

状态,否则就被抛出IllegalStateException,这也就是说同一个AsyncTask只能使用一遍;接下来设置状态为RUNNING,调用callback

方法onPreExecute,设置mWorker的mParams字段为用户提供的值,接着在executor中执行mFuture,最后返回this引用。

  最后剩下的我们一块看看,代码如下:

 =   InternalHandler "unchecked", "RawUseOfParameterizedType" =
                    result.mTask.finish(result.mData[0    WorkerRunnable<Params, Result>  Callable<Result>"RawUseOfParameterizedType"   AsyncTaskResult<Data>==

可以看出finish方法是UI线程在收到MESSAGE_POST_RESULT消息的时候调用,如果取消了则调用onCancelled(result),否则调用

onPostExecute(result);最后都设置了task的状态为FINISHED。同样的,onProgressUpdate是在收到MESSAGE_POST_PROGRESS

被调用的。最后的2个类都是持有数据的类,WorkerRunnable<Params, Result>是一个Callable<Result>并且持有后台task运行需要用到

的参数列表,后台线程post Message的时候会将结果包装成一个AsyncTaskResult发送出去。

  至此AsyncTask的关键代码都已经分析完毕,我们可以看出AsyncTask实际上是对java.util.concurrent包里Executor,Callable,FutureTask

以及Handler的一个综合应用,属于简化开发人员流程的一个工具类。

用户评论