AsycnTask的实现原理

AsyncTask出现的意义

        大家都知道android中的UI更新都应该在主线程上完成(并不是完全对),但有时候显示的数据是从网络获取的,而这个方法是异步完成的,所以中间要有个桥梁来链接这连个东东,这就是Handler。我们在异步线程中通过Handler来发送消息,然后在消息的回调中更新UI,这看上去还不错,但是google的开发同学不这样认为,因为当一个任务有多个线程时代码会显得臃肿不利于阅读(让人读懂你的代码比你写代码更重要,因为它考验了你的设计能力),为了让这两个线程更好的配合工作,AsycnTask类的出现很好的解决了这个问题,它既有异步线程执行的优点,又有在异步线程执行前后在主线程执行的优点,例如任务开始时在UI上告诉用户我已经开始了,然后后台咚咚咚的干活,最后在UI上呈现你的劳作结果,所以看上去这个类有他存在的价值,下面讲一下AsyncTask的使用。

AsycnTask的实现原理_第1张图片

AsyncTask工作的入口newMyAsyncTask().execute("par"); 对于这个类的使用就不做过多的介绍了,这篇文章主要讲的是实现原理。调查从入口开始那就是execute这个方法,看看这里面做了什么?只有一行代码如下图

我们继续往下看

AsycnTask的实现原理_第2张图片

这个方法是逻辑处理的地方,看看做了什么

1.首先会检测先当前AsyncTask的状态,AsyncTask有三种PENDING、RUNNING、FINISHED,如果发现是不是PENDING状态则会抛出异常,这就是调用两次execute会抛出异常的原因。

2.然后将当前的状态置为运行状态,调用了onPreExecute方法,也就是说这个方法会在调用execute的线程里执行,而onPreExecute方法主要用于通知UI更新,告知用户任务开始,所以建议调用execute的方法在UI中执行,这就是为什么在一开始的注释中不是在UI线程回调的原因。

3.将参数指向到workr的params中

4.最后调用了exec.execute方法,而这个exec是传入进来的 而mFuture是在AsyncTask的构造方法中创建的,我们先看下这个execu的来头,回去看看。

看来这个sDefaultEexecute是关键了,看下它创建的地方如下图

AsycnTask的实现原理_第3张图片

        我们发现这个execute并没有做什么只是将runnable封装了下放入了mTasks队列中,然后取出task后执行THREAD_POOL_EXECUTOR的execute方法,看来真正执行的地方因该只在这个方法中。从名字上看像是个线程池的对象,我们继续看execute这个方法,发现是个Executor的接口,到这基本就有了答案,最终执行的是线程池,回过头来看下这个THREAD_POOL_EXECUTOR类创建的地方。如下图

AsycnTask的实现原理_第4张图片

不错就是创建了一个线程池对象,这是几个关键的参数如下图

AsycnTask的实现原理_第5张图片

        核心线程池的个数是2-4个,最大线程数的个数是cpu个数*2+1,闲置线程回收时间是30秒。等待队列的个数是128个,线程池工厂里面对线程进行了命名(关于线程的讲解请参考Android中的多线程-(叫android只是好听 其实是java中的) - ),现在执行的方式已经找到了采用的是线程池的方式,那我们刚才说的exec.execute()的参数mFuture就是执行的任务了,mFuture的创建在构造方法中,回过头来看看构造方法的代码如下图

AsycnTask的实现原理_第6张图片

创建了一个FutrueTask将mWorker作为参数,而这个mWorker继承了Callable,所以在创建实例的时候实现了call方法,这个call方法里又调用了doInBackGround方法,call是被添加到线程池中执行的,所以doInBackGround是在异步线程中执行的。好的,到现在差不多弄明白onPreExecute和doInBackground这个两个方法了,感觉是不是很简单呢,我们在往下看剩下的几个方法。

        既然onPostExecute()这个方法用于线程工作完成后在主线程中更新UI的,他的原理可能是通过一个handler持有mainLoop对象完成的,我们看下postResult(result)方法如下图

AsycnTask的实现原理_第7张图片

回去一个handler然后发送了一个消息,将含有结果和AsyncTask的对象发送了出去,这个getHandler()定会有文章,代码如下图

AsycnTask的实现原理_第8张图片

获取了一个内部的Handler 我们继续看InternalHandler()类。

AsycnTask的实现原理_第9张图片

到这里似乎找到了onPostExecute在主线程回调的原因,因为生成这个Handler的时候Looper是MainLooper也就是主线程的looper,所以回调的方法是在主线程。onProgressUpdate这个方法也很好解释了,同样是通过这个handler在主线程回调的,看下代码

AsycnTask的实现原理_第10张图片

和onPostExecute的几乎一样都是通过handler进行更新,到现在是不是弄清楚了AsyncTask的原理了呢。AsyncTask不是万能的也有好多的缺点.

缺点

        1.由于使用的是线程池其缺点也比较明显,由于核心线程池的个数为2-4个,如果当所有线程池里面的线程都在干活,所以你添加的任务可能不会被立刻执行,因此AsyncTask不适合做太耗时的任务。

        2.如果AsyncTask是Activity的内部类,那么该类会持有Activity的对象,所以当Activity销毁是如果AsyncTask还没有执行完会导致Activity无法被回收。AsyncTask作为单独的类时也要注意。

小结:

          1.onPreExecute在调用execute的线程里执行

          2.AsyncTask主要是通过内部创建的线程池来运行doInBackground

          3.onPostExecute和onProgressUpdate在主线程执行的原因是通过持有MainLooper的Handler来完成的。


你可能感兴趣的:(AsycnTask的实现原理)