年后工作稍没那么紧张,重新阅读一些Android源码,以此记录。
AsyncTask的整体实现原理可以理解为Handler+线程池。
可以看到AsyncTask源码中前面的一部分属性都是为了创建 THREAD_POOL_EXECUTOR 线程池而做准备。
在上图的最下面,可以看到定义了一个SerialExecutorl类型的 SERIAL_EXECUTOR
通过代码可以看出 SerialExecutor 主要控制任务串行的执行,在execute方法中将基于传入的Runnable封装的一个Runnable插入到任务队列中,被封装后的Runnable在执行结束后能自动的调用下一个任务进行执行。而在scheduleNext()方法中,最终将任务交给了前面定义的THREAD_POOL_EXECUTOR 进行执行。
再回到上面的参数定义部分:
可以看到最终将定义好的SERIAL_EXECUTOR 赋值给AsyncTask默认的线程池变量sDefaultExecutor。
接着往下看,可以看到源码中定义了一个InternalHandler 类型的sHandler变量
很明显这个Handler就是用来处理子线程发送过来的消息的
而默认情况下sHandler是与主线程的Looper绑定的。
接下来就可以看到两个比较重要的属性,分别是WorkerRunnable 类型的mWorker和FutureTask类型的mFuture。
可以看到WorkerRunnable继承自Callable,而Callable与Runnable接口相似,主要区别在于其call()方法有返回值,而Runnable的run()方法没有返回值。
在AsyncTask的构造函数中可以看到,worker重写的call方法中调用了一个我们非常熟悉的方法 doInBackground(mParams)
而在后面我们将看到worker将被装进FutureTask中,而FutureTask将被execute到前面定义的线程池中,从而实现在子线程中执行doInBackground(mParams)方法。
而FutureTask实际上是继承自Runnable对象,所以可以将FutureTask对象传递给线程池进行执行。
接下来关注一下FutureTask中的两个方法 done() 和 get()
done():该方法会在任务被执行完毕后调用,我们回到AsyncTask的构造函数
可以看到AsyncTask重写了done()方法,并最终通过handler发送消息,在主线程中调用了一个我们很熟悉的方法onPostExecute(result);
get():细心的同学可能已经发现在AsyncTask的构造函数里初始化FutureTask的时候,重写的don()方法内已经调用了get()方法,从上面的代码中可以看到,get()方法返回的是用户在初始化AsycTask时传递进来的Result类型的值;需要注意的是get()方法是阻塞式的等待callable的call()方法的返回值。
至此,整个AsyncTask的源码主要的逻辑应该是理清楚了,主要就是Handler+线程池以实现异步任务和主线程回调。
希望文章能让您有所收获,感谢您的阅读!