android开发-AsyncTask源码解析

来源:互联网 发布:杀师案 知乎 编辑:程序博客网 时间:2024/06/07 15:42

AsyncTask的原理还是线程池+InternalHandler(继承于Handler)


一、AsyncTask五个核心方法

onPreExecute 主线程执行 在异步任务执行之前会先被调用 用来做初始化工作

doInBackground(Params ...param) 在线程池中执行,此方法用来执行异步任务  在此方法中 通过publishProgress方法来更新任务进度,publishProgress会调用onProgressUpdate方法,此方法需要返回计算结果给onPostExecute

onProgressUpdate(Progress...values) 在主线程中执行,当后台执行进度发生改变时 调用 publishProgress 方法的时候,此方法会被调用

onPostExecute(Result result)在主线程中执行 异步任务执行之后  此方法会被调用 result就是doInbackground的返回值

onCancelled() 调用cancel的时候,任务会被取消,会调用onCancelled方法 这个时候onPostExecute则不会调用


二、AsyncTask的类加载必须在主线程中加载,在android5.0系统源码中,可以查看ActivityThread的main方法,他会调用AsyncTask的init方法,这就满足了AsyncTask的类必须在主线程中进行加载的这个条件

AsyncTask的对象必须在UI线程调用

execute方法必须在UI线程调用

一个AsyncTask对象只能执行一次,即只能调用一次execute方法 否则会报运行时异常

在android3.0之后开始 AsyncTask采用了线程串行执行任务,尽管如此 我们仍然可以通过AsyncTask的executeOnExecutor方法来并行的执行任务

task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,10);

AsyncTask.THREAD_POOL_EXECUTOR是静态模块中执行  他就是线程池 


三、源码分析

execute->executeOnExecutor()

然后紧接着会执行onPreExecute 这是在主线程中执行的

executeOnExecutor需要指定一个线程池,我们默认的线程池是Executor sDefaultExecutor = SERIAL_EXECUTOR;

Executor sDefaultExecutor = SERIAL_EXECUTOR;
Executor SERIAL_EXECUTOR = new SerialExecutor();


SERIAL_EXECUTOR是一个假的线程池 只是实现了Executor的接口 并没有执行开启子线程


这个线程池的功能就是为了保证线程能够串行执行 一次只执行一个任务
执行executeOnExecutor方法的时候 
会把Runnable回调传入进去,在SerialExecutor的execute执行
在这个方法里面只是把Runnable放入了一个队列ArrayDeque里面
ArrayDeque是一个双向队列 能从队尾和队头添加数据
添加完队列之后 会判断当前是否有队列里的任务正在执行

if(mActive==null){
 scheduleNext();
}
mActive是表示当前正在执行的Runnable
如果没有执行 那么在scheduleNext方法中, 真正的线程池就开始执行了
 if ((mActive = mTasks.poll()) != null) {
         THREAD_POOL_EXECUTOR.execute(mActive);
 }


然后开始执行 WorkerRunnable mWorker这个任务,WorkerRunnable是一个实现了Callable接口的类,

由于我们不需要get结果阻塞等待获取结果,所以没有调用mFuture.get(); 所以线程不会阻塞

这里的任务是在子线程里面进行的

所以可以看到doInBackground在这里执行
之所以用Callable的FutureTask,而不用Runnable  是因为Callable是可以所以取消的 方便管理线程



执行完获取完结果之后  执行了postResult
这里通过Handler 发送一个MESSAGE_POST_RESULT消息 让任务切换到主线程中去执行
通过InternalHandler 我们可以看到,有两种消息类型
1、MESSAGE_POST_RESULT  处理结束时候的结果
2、MESSAGE_POST_PROGRESS 调用publishProgress会调用


MESSAGE_POST_RESULT  对应的会执行result.mTask.finish();
其中result是AsyncTaskResult类型,它里面包含了当前的AsyncTask以及对应的结果
这个AsyncTaskResult放在了Message中的obj里面了


所以result.mTask.finish()方法被调用后,我们的AsyncTask的finish方法会被调用
private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }
如果是cancel方法 导致取消的 会执行第一个onCancelled方法
如果是正常结束的  会执行onPostExecute方法



在android3.0以上设备

AsyncTask执行的是串行策略

在android3.0之下

AsyncTask执行的是并行的策略

如果想在3.0以上的设备执行并行策略 可以调用executeOnExecutor方法

指定我们的线程池AsyncTask.THREAD_POOL_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;}