AsyncTask解析



    AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新UI

 

Public abstract class AsyncTask<Params, Progress, Result>.

 

AsyncTask是一个抽象的泛型类,它提供了三个泛型参数。

Params:启动AsyncTask时传入的数据类型(可为Void

Progress:表示进度的数据类型(可为Void

Result:任务执行完毕后返回的数据类型(可为Void

 

AsyncTask提供了四个核心方法:

(1)onPreExecute():在主线程执行,异步任务调用之前,此方法会被调用。

(2)doInBackground(Params...params),在线程池中执行,此方法用来执行异步任务,params参数表示异步任务的输入参数。此方法中可以通过publishProgress方法来更新任务的进度,publishProgress方法会调用onProgressUpdate方法。还有需要返回计算结果给onPostExeute方法。

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

(4)onPostExecute(Result result),在主线程中执行,在异步任务执行之后,此方法会被调用,其中result参数是后台任务的返回值,即doInbackground的返回值。

还有一个onCancelled()方法,同样在主线程中执行,当异步任务被取消的时候,onCancelled()方法会被调用,这个时候onPostExecute则不会被调用。

几个注意的地方:

AsyncTask的类必须在主线程中加载,即第一次访问必须发生在主线程。Android 4.1以后已经自动完成,在ActivityTHread.main方法中,他会调用AsyncTaskinit方法,这就满足了这个条件。

AsyncTask的对象必须在主线程中创建

Execute方法必须在UI线程调用

不要在程序中直接调用AsyncTsak的那四个方法

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


Android 3.0以后是开始串行执行任务,但是我们可以通过AsyncTaskexecuteOnExecutor方法来并行地执行任务。

AsyncTask的工作原理

先从execute方法开始分析,首先调用executeOnExecutor

(sDefaultExecute, params)方法。这里sDefaultExecute实际上是一个串行的线程池。

   

这里首先判断状态,如果AsyncTask正在运行或者已经运行过,就会抛出异常。这里就可以解释为什么execute方法只能调用一次。    

接下来AsyncTask.onPreExecute方法最先执行。

然后调用线程池的execute(mFuture)方法。

params参数放入Callable<params>中。

 

mFuture的实际类是FutureTaskFutureTask继承RunnableFuture<V>接口,它可以包装Callable<V>Runnable然后实现其中的线程。而且调用get方法可以引起主线程阻塞,直到获取到Callablecall()方法的返回值。

AsyncTask的构造方法中,会为我们创建FutureTask,Callable对象,将Callable<V>放入 FutureTask中,FutureTask实现了Runnable接口,关于这部分内容可以看这篇文章。

https://blog.csdn.net/longshengguoji/article/details/41126119


          

    总的来说,构造方法做了如下的事情:

    1.初始化了两个变量,mWorker和mFuture,并在初始化mFuture的时候将mWorker作为参数传入。mWorker是一个Callable对象,mFuture是一个FutureTask对象

     2.mWorker中的call()方法执行了耗时操作,即result = doInBackground(mParams);,然后把执行得到的结果通过postResult(result);,传递给内部的Handler跳转到主线程中。在这里这是实例化了两个变量,并没有开启执行任务。

    

再来看SerialExecutor.execute(Runnable r)方法:

FutureTask在这里充当了Runnable的作用,SerialExecutor 是个静态内部类,是所有实例化的AsyncTask对象公有的,SerialExecutor 内部维持了一个队列,通过锁使得该队列保证AsyncTask中的任务是串行执行的,即多个任务需要一个个加到该队列中,然后执行完队列头部的再执行下一个,以此类推。

由此可见SerialExecutor类仅仅为了保持任务执行是串行的,实际执行交给了另一个线程池THREAD_POOL_EXECUTOR。

AsyncTask中主要的就是两个线程池和一个Internal,Handler,其中SerialExecutor用于任务的排队,而线程池THREAD_POOL_EXECUTOR用于真正地执行任务。


execute中会调用FutureTask.run方法,最终调用Callable<params>中的call方法。即刚开始我们在构造方法中所看到的call方法,因此call方法最终会在线池中执行。

Call方法中,首先将mTaskInvoked设为true,表示当前任务已经被调用过了,然后执行AsyncTaskdoInBackground方法,接着将其返回值传递给postResult方法。


 

再来看postResult方法

他会通过sHandler发送一个MESSPOST_RESULT消息,调用AsyncTaskfinish方法。finish方法中逻辑比较简单,如果AsyncTask被取消执行了,就调用onCancelled方法,否则就调用onPostExecute方法,该方法的参数就是doInBackground的返回值。

 

还有就是sHanlder是一个静态的Handler对象,为了能够执行环境切换到主线程,这就要求sHandler这个对象必须在主线程中创建,因此变相要求AsyncTask的类必须在主线程中加载。

最后有一个就是AsyncTask3.0以后的版本全都改成了串行执行。

 

关于AsyncTask的使用注意

1.生命周期

AsyncTask不与任何组件绑定生命周期,所以在Activity/或者Fragment中创建执行AsyncTask时,最好在Activity/Fragment的onDestory()调用 cancel(boolean);

2.内存泄漏

如果AsyncTask被声明为Activity的非静态的内部类,那么AsyncTask会保留一个对创建了AsyncTask的Activity的引用。如果Activity已经被销毁,AsyncTask的后台线程还在执行,它将继续在内存里保留这个引用,导致Activity无法被回收,引起内存泄露。

3.结果丢失

屏幕旋转或Activity在后台被系统杀掉等情况会导致Activity的重新创建,之前运行的AsyncTask(非静态的内部类)会持有一个之前Activity的引用,这个引用已经无效,这时调用onPostExecute()再去更新界面将不再生效。


 

 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值