Android的AsyncTask类的解读
来源:互联网 发布:04年总决赛科比数据 编辑:程序博客网 时间:2024/05/22 07:39
AsyncTask类,因为这两个类使我们在Android进行耗时的操作的时候,不影响主线
程的情况下经常使用的两个类,我们先来看一下AsyncTask类源码中定义的变量:
看到这些字段之后,我们可能发现,貌似好多类型我们都不知道,所以这里在先说AsyncTask类之前,需要做一些准备工作,介绍
一些这些类型。其实我们还需要了解一下Java5.0加入的并发库的相关知识,参看这篇文章:
http://blog.csdn.net/jiangwei0910410003/article/details/20373497
第一、ThreadFactory类
看看他的源码:
好吧,好简单呀,就是一个接口,有一个回调方法newThread,用于创建一个Thread.第二、BlockQueue类
是一个阻塞队列,这里就不做介绍了,参考这篇文章:
http://blog.csdn.net/jiangwei0910410003/article/details/20373497
第三、ThreadPoolExecutor类
主要是看他的构造函数的几个参数的含义,就能够了解这个类的作用了:
看这个参数很容易让人以为是线程池里保持corePoolSize个线程,如果不够用,就加线程入池直至maximumPoolSize大小,如果还不够就往workQueue里加,如果workQueue也不够就用RejectedExecutionHandler来做拒绝处理。
但实际情况不是这样,具体流程如下:
1)当池子大小小于corePoolSize就新建线程,并处理请求
2)当池子大小等于corePoolSize,把请求放入workQueue中,池子里的空闲线程就去从workQueue中取任务并处理
3)当workQueue放不下新入的任务时,新建线程入池,并处理请求,如果池子大小撑到了maximumPoolSize就用
RejectedExecutionHandler来做拒绝处理
4)另外,当池子的线程数大于corePoolSize的时候,多余的线程会等待keepAliveTime长的时间,如果无请求可处理就自行销毁
内部结构如下所示:
从中可以发现ThreadPoolExecutor就是依靠BlockingQueue的阻塞机制来维持线程池,当池子里的线程无事可干的时候就通过
workQueue.take()阻塞住。
第四、InternalHandler类
这个类我们在后面详细分析AsyncTask类的时候,会发现他其实就是一个Handler,所以这里我们可以看出AsyncTask类其实是基于
Handler+并发库技术实现的,后续解析代码的时候会体现的更明显。
第五、Status类型
这个类型其实是一个枚举,我们这里的关注点不是类型,而是修饰符volatile,这个修饰符的作用这里不做介绍了,请看下面一篇文
章:http://blog.csdn.net/jiangwei0910410003/article/details/20369811
第六、WorkerRunnable类
这个类是在AsyncTask类中定义的:
他是个抽象类,实现了Callable接口,这里的Param和Result是AsyncTask定义的泛型类型第七、FutureTask类
在看一下RunnableFuture接口:
FutureTask类其实是实现了Future和Runnable接口,具备了这两个接口的功能,关于Future和上面的Callable可以参考下面文章:http://blog.csdn.net/jiangwei0910410003/article/details/20373497
注意:刚才也说了AsyncTask其实是基于Handler+并发库技术实现的,但是并发库中也是有很多知识的,这里用到的核心技术就
是Future+Callable
下面来看看一下Future类的主要方法:
1) boolean cancel(boolean mayInterruptIfRunning):试图取消对此任务的执行。如果任务已完成、或已取消,或者由于某些其
他原因而无法取消,则此尝试将失败。当调用 cancel 时,如果调用成功,而此任务尚未启动,则此任务将永不运行。如果任务已经
启动,则 mayInterruptIfRunning 参数确定是否应该以试图停止任务的方式来中断执行此任务的线程。此方法返回后,对 isDone() 的
后续调用将始终返回 true。如果此方法返回 true,则对 isCancelled() 的后续调用将始终返回 true。
2)boolean isCancelled():如果在任务正常完成前将其取消,则返回 true。
3)boolean isDone():如果任务已完成,则返回 true。 可能由于正常终止、异常或取消而完成,在所有这些情况中,此方法都将
返回 true。
4)V get()throws InterruptedException,ExecutionException:如有必要,等待计算完成,然后获取其结果。
5)V get(long timeout,TimeUnit unit) throws InterruptedException,ExecutionException,TimeoutException:如有必要,最
多等待为使计算完成所给定的时间之后,获取其结果(如果结果可用)。
第八、AtomicBoolean类
这个类,我们可能不会经常用到,但是我们通过它的名字会发现他是对Boolean类型添加了原子操作的功能,那么当然还有其他7种
基本类型对应的类(AtomicInteger等)
看一下他的源码:
value值是个int类型的,这里使用int类型来模拟Boolean类型的,0就是false,1就是true.
这里有一个很重要的类Unsafe,但是这个类,他是属于JDK的核心包中,所以要查看他的源码的话,只能从网上去搜了:http://www.docjar.com/html/api/sun/misc/Unsafe.java.html
这个类是用于执行低级别、不安全操作的方法集合。尽管这个类和所有的方法都是公开的(public),但是这个类的使用仍然受限,
你无法在自己的java程序中直接使用该类,因为只有授信的代码才能获得该类的实例。从上面的描述,可以了解到该类是用来执行
较低级别的操作的,比如获取某个属性在内存中的位置,不过一般人很少会有这样的需求。
上面的静态代码块中的代码的功能就是用来获取AtomicBoolean实例中的value属性在内存中的位置。这里使用了Unsafe的
objectFieldOffset方法。这个方法是一个本地方法, 该方法用来获取一个给定的静态属性的位置。
在来看一下AtomicBoolean类的一个重要的方法:
这里有个疑问,为什么需要获取属性在内存中的位置?在AtomicBoolean源码中,在这样几个地方使用到了这个valueOffset值:
查找资料后,发现lazySet方法大多用在并发的数据结构中,用于低级别的优化。compareAndSet这个方法多见于并发控制中,简称
CAS(Compare And Swap),意思是如果valueOffset位置包含的值与expect值相同,则更新valueOffset位置的值为update,并返回
true,否则不更新,返回false。这里可以举个例子来说明compareAndSet的作用,如支持并发的计数器,在进行计数的时候,首先
读取当前的值,假设值为a,对当前值 + 1得到b,但是+1操作完以后,并不能直接修改原值为b,因为在进行+1操作的过程中,可能
会有其它线程已经对原值进行了修改,所以在更新之前需要判断原值是不是等于a,如果不等于a,说明有其它线程修改了,需要重
新读取原值进行操作,如果等于a,说明在+1的操作过程中,没有其它线程来修改值,我们就可以放心的更新原值了。
AsyncTask源码解析
所有的类型都说完之后,下面来看一下AsyncTask类的源码
一、构造方法
首先来看一下构造方法:
构造方法主要初始化WorkerRunnable类和FutureTask类
在WorkerRunnable的call方法中主要调用了postResult(doInBackground(mParams)),之前看到了WorkerRunnable实现了Callable接口的,这里就实现了他的call方法,执行完这个方法之后,需要返回执行之后的结果
先看一下:doInBackground方法:
是一个抽象的方法,这个需要我们自己去实现它再来看一下postResult方法,这个方法里面我们可以看到就是将Result类型的结果值发送给InternalHandler进行处理
看一下InternalHandler类的定义:
这个Handler中处理两个状态的信息:MESSAGE_POST_RESULT:处理结果的
这里调用了finish方法:
在这个方法里面,会判断取消状态,然后执行对应的方法,因为任务结束有两个原因:一个是被取消了:回调onCancelled方法
一个是完成:回调onPostExecute方法
MESSAGE_POST_PROGRESS:处理过程的
这里调用onProgressUpdate方法
这个方法也是我们可以重写的方法下面再看一下FutureTask类的初始化:
这里调用了一个重要的方法:postResultIfNotInvoked(get());
FutureTask的构造方法需要传递一个Callable接口对象进去,内部可以通过调用这个接口对象的call方法,获取结果,可以查看一下FutureTask类的源码:
构造方法:
保存一下Callable接口对象
因为也实现了Runnable接口,所以要实现run方法:在这个run方法中我们看到会调用c.call方法获取结果。然后set(result),以后就可以通过get()方法获取到result,在看一下set方法的源码:
看一下finishCompletion方法:
这里就看到调用了FutureTask类的done方法:这是个空方法,需要子类重写这个方法。下面就看到重写这个done方法这里FutureTask重写了done方法,在这个方法中处理(WorkerRunnable)Callable任务执行的结果的。
首先来看一下get()方法:
这里就是调用了FutureTask的取数据方法get,获取执行结果再来看一下postResultIfNotInvoked方法:
这个方法会判断一下,当前的Task有没有执行过,如果没有执行过,就执行postResult方法二、execute方法
AsyncTask类的构造方法看完之后,下面来看一下他的执行方法execute再看executeOnExecutor方法:
段定义的时候说过他,主要使用任务池中拿去Runnable去执行。这里传递进来的是我们在构造方法中初始化的FutureTask类,那么
就是在这里执行它的run方法。
在这个方法中调用onPreExecute方法:
这个也是一个空方法,我们可以去重写的,然后就开始使用执行器执行任务,这里需要将任务FutureTask传递进去。
这里我们可以看到,AsyncTask类的三个主要的方法:
doInBackground(...):他是一个抽象的方法,需要实现的
onPreExecute(...):是开始预备的方法,我们可以重写(可选择的)
onPostExecute(...):是执行结束之后的方法,我们可以重写(可选择的)
onProgressUpdate(...):是执行中的方法,我们可以重写(可选择)
通过上面的分析,我们可以看到只有doInBackground方法是在线程池中执行的,就是在WorkerRunnable中的call方法中。其他的两
个方法都是在外部线程中执行的
onPreExecute是在AsyncTask类的execute方法中执行的。
onPostExecute是在finish方法中执行的,而finish方法又是在InternalHandler中的MESSAGE_POST_RESULT状态下执行的。
onProgressUpdate是在InternalHandler中的MESSAGE_POST_PROGRESS状态下执行的
(这里的InternalHandler采用的是默认构造方法创建的,所以他的Looper是创建AsyncTask类的线程,如果你想在子线程中创建
AsyncTask的话,会报异常的,必须将该线程Looper.prepare一下才可以)。
总结
1、AsyncTask类中有Param,Result等类型,这些是泛型类型,所以这里不要混淆就可以了
2、AsyncTask类用到的技术:Handler+FutureTask(实现了Future和Runnable接口)+Callable
3、AsyncTask类的执行周期:
1)在构造方法中,
初始化WorkerRunnable(实现了Callable接口),实现call方法,在这个方法中回调AsyncTask类的doInBackground方法,并且返回一
个result值。
初始化FutureTask(实现了Runnable,Future接口),复写了FutureTask中的done方法,在这个方法中通过FutureTask的get方法获取
result。同时我们在初始化的时候需要传递一个Callable(WorkerRunnable)类型,之前看FutureTask的源码发现,在他的run方法中,
会调用传递进来的Callable类型的call方法,并将这个方法的返回值result在调用set方法设置一下,同时会调用done方法。
2)在execute方法中
调用了executeOnExecutor方法,在这个方法中会调用AsyncTask类的onPreExecute方法,然后在调用ThreadPoolExecutor开始执
行FutureTask任务
3)在InternalHandler定义中
有两个状态:
一个是执行完成了,会调用finish方法,在这个方法中会调用AsyncTask类的onPostExecute方法
一个是执行中的方法,会调用AsyncTask类的onProgressUpdate方法
这个Handler的Looper是创建AsyncTask类的线程Looper。
- Android的AsyncTask类的解读
- Android的AsyncTask类的解读
- Android的AsyncTask类的解读
- android的类AsyncTask
- android的AsyncTask类
- android AsyncTask 源码解读
- android AsyncTask类的使用
- Android 的AsyncTask使用
- Android的AsyncTask
- Android AsyncTask的用法
- Android AsyncTask的优势
- Android AsyncTask的使用
- Android的AsyncTask
- Android AsyncTask 的使用
- android AsyncTask的用法
- android 的 AsyncTask 详解
- Android AsyncTask的用法
- android的AsyncTask分析
- Centos设置开机启动Apache和Mysql
- mac 装 mongodb
- Android Canvas 基本使用
- oracle 数据库的常用查询对象
- 用户界面框架jQuery EasyUI示例大全之DataGrid(4/4)
- Android的AsyncTask类的解读
- iOS经典讲解之Apple Pay开发
- lvs:Linux virtual server八种算法
- linux下游戏服务器的启动
- 细分着色器
- Ios生成二维码
- ZOJ1060
- Linux下常用命令整理
- $( function() {} );与( function($){} )(jQuery);的异同