您的位置:首页 > 其它

关于AsyncTask运行机制

2016-09-05 21:12 99 查看
AsyncTaask中有三个方法比较重要的方法,onPreExecute(),doInBackground(),onPostExecute(),分别在主线程,子线程,主线程执行,那么,画红线的地方,就是参数类型要一致的地方, 我们就来探究一下他们是怎么去执行的。

我们先找到AsyncTask的execute方法()

可以看到,方法接收一个可变的参数
判断中Status是什么呢,是判断AsyncTask运行的三个状态的枚举,包括未运行(PENDING), 正在运行(RUNNING),运行结束(FINISHED).
这个判断是否未运行,如果不是未运行状态,即是运行中或者运行借宿的状态,那么就抛异常。这就是为什么AsyncTask只能执行一次。

如果是在未运行的状态,执行判断外的语句,将状态改为运行中状态。
接下来执行了onpreExecute();这里就调用了三个重要方法中的第一个,而这个时候,onpreExecute()还没有进入到子线程中,这里,我们在哪个线程中调用的AsyncTesk的execute()方法,那么onpreExecute()就在哪个线程中执行,现在在主线程中调用的AsyncTesk的execute() ,所以onpreExecute() 在主线程中执行。

接下来,把传进来的参数给了mWorker,那么mWorker是什么呢

它是一个WorkRunnable类型的参数,那么WorkRunnable是什么类呢?

WorkRunnable是AsyncTask的内部类,它将传入的参数给了一个Params[]的数组,可以看到,WorkRunnable 实现了Callable接口。
那么意思就是,在调用的AsyncTesk的execute()的时候的参数传到了这里。

我们再来看,sExecute是什么呢,它还有一个ecxcute()的方法?

这是一个线程池,约束了线程池的一些条件。那么mFuture又是什么呢?为什么要把它传给线程池的ecxcute()呢?

mFuture是一个FutureTask类型的参数,那么FutureTask又是什么呢?

而RunnableFuture是一个实现了Runnable接口的子类,只有一个空实现的run()方法。所以这里我们可以看作FutureTask是实现了Runnable接口的。

 我们看到,在FutureTask的构造方法中,需要传入一个Callable类型的参数,我们再想想,刚刚的mFutrure是实现了Runnable的,那么它就肯定有run()方法,我们可以大胆猜测一下,sExecute 的execute()方法在执行的时候,执行了mFutrure 的run()方法,run()方法是在子线程执行的,那么,doInBackground()方法,肯定是在这里的执行了,那么mFuture在哪创建的呢,mWorker又是在哪里创建的呢,他们都干了些什么?

我们先小结一下,在AsyncTask的execute()执行的时候,将参数赋值给了mWorker的mParams,把参数放在了Params[]数组中,然后执行了线程池sExecute 的execute()方法,将mFuture传入了

我们看到,在Asynctask的构造方法中,初始化了mWorker和mFuture.

在mWorker的测call方法中,调用了doInBackground方法,然后又将mWorker当作参数传给了通过FutureTask的构造方法传给了mFuture。这里重写了FutureTask 的done()方法。

我们想想之前,在FutureTask的构造方法中,接受了一个Callable的参数,这里就是把mWorker对象给传到了这里,在FutureTask的构造方法中,当callable(mWorker)不为空时,又把mWorker给了Sync的构造,Sync是FutureTask的一个内部类,在Sync中拿到mWorker交给了this.callable,也就是给了自己的callable。

在Sync中有一个innerRun(),在innerRun()中,执行了callabke(mWorker)的call方法,也就是执行了mWorker的call()方法。

那么innerRun()在哪执行的呢?

在FutureTask的run方法中,执行了innerRun(),我们知道,mFuture是相当于实现了Runnable接口的。所以在线程池mExecute执行execture()的时候,就相当于在在子线程中执行了mFuture的run(),也就调用了doInbackground(),在子线程中执行。

那么接下来,就该看是如果拿到doInbackground()方法执行的结果并返回主线程的。
我看可以看到,在执行了innerRun()之后,执行了一个set(result)方法,把结果set了,set()方法,是FutureTask的方法,在set()中执行innerSet(),在innerSet()干了什么呢?

我们看看,在innerSet()中,把结果v(原来的result)赋值给了当前的result(result是Sync的一个成员变量),之后执行了done方法,之前我们看到,在mFuture初始化的时候,重写了done()。这里还是在子线车程中。

在done()中,调用了Reslut的get方法,调用了Sync的innrtGet()

那么在Sync的innrtGet()中干什么呢?

返回了Sync中的成员变量result,也就是之前的doInBackground()执行的结果。

我们再看看在done()的下面的代码

这里new了一个AsyncTaskResult对象,还把当前的AsyncTask和结果result都传过去了,那么AsyncTaskResult中干了什么呢?

AsyncTaskResult就是一个bean类

那么在message.sendToTarget的时候,就把当前的AsyncTask和结果result当作消息发送出去了给了handler,在handlerMessage()中

调用了finish(),把计算的结果传给了finish()

在finish()中,接收到结果,给了onPostExecute(),同时把AstncTask对象的状态置为未执行,方便执行下一次任务,这里,就把结果给回了主线程中的onPostExecute()方法。可以在主线程中使用doInBackground()执行的结果了。

总结一下:在AsyncTask的对象创建的时候,初始化mWorker(实现Callable)和mFuture(实现Runnable),在mFuture对象创建的时候,把mWorker当作参数传给了mFuture。
调用execute()的时候,先执行了onPreExecute(),在当线程中运行,之后将mFuture交给线程池mExecute,在子线程中执行mFuture的run方法,也就执行了Sync的innerRun(),既是执行了mWorker的call方法,也即是执行了doInBackground()方法,并把结果set在了Sync的result中,在set的时候,调用done()方法,早done()中,使用get()拿到了result,并将result和当前的AsyncTask对象封装在AsyncTaskResult
对象中,发送给了handler的handlerMessage方法,回到了主线程,执行AsyncTaskResult的finish方法,将result交给了主线程的onPostExecute(result)方法,同时将状态恢复为未执行,方便下一次任务的执行。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: