美文网首页
AyncTask源码解析

AyncTask源码解析

作者: 忘我_c482 | 来源:发表于2020-05-04 20:25 被阅读0次

    AsyncTask是个abstract类,所以在使用时需要实现一个AsyncTask的具体实现类,一般来说会覆盖4个方法,我们以前面所说的从网络中下载一张图片,然后更新到UI控件来说明:
    (1)onPreExecute():在执行后台下载操作之前调用,将下载等待动画显示出来,运行在主线程中;
    (2)doInBackground():核心方法,执行后台下载操作的方法,必须实现的一个方法,运行在子线程中;这个方法是执行在子线程中的。在onPreExecute()执行完后,会立即开启这个方法。
    (3)onProgressUpdate():在下载操作doInBackground()中调用publishProgress()时的回调方法,用于更新下载进度,运行在主线程中;
    (4)onPostExecute():后台下载操作完成后调用,将下载等待动画进行隐藏,并更新UI,运行在主线程中;

    构造方法

    AsynTask构造方法.png

    mWorker代表了AsyncTask要执行的任务,是对Callable接口的封装,意味着这个任务是有返回值的。


    WorkerRunable.png

    mFuture代表了AsyncTask要执行的任务的返回结果,其实就是个FutureTask,安装FutureTask标准用法,mWorker作为Callable被传给了mFuture,那么mFuture的结果就从mWorker执行的任务中取得。仔细看mWorker,return语句返回的结果就是我们前面所说的doInBackground()的执行结果。

    execute执行流程

    查看源码execute()-->executeOnExecutor(sDefaultExecutor, params))-->exec.execute(mFuture)
    到了这一步,将mFuture传递给了AsyncTask的执行器进行执行。AsyncTask的执行器缺省是sDefaultExecutor。
    找到成员变量sDefaultExecutor,最终定位到


    image.png

    SerialExecutor是对JDK里Executor的一个实现,被声明为一个静态变量,我们仔细看SerialExecutor的实现,


    image.png
    内部声明了一个双端队列ArrayDeque类型的mTasks(双端队列中offer方法表示从队列尾插入,poll()表示从队列头获取元素)。
    每次调用execute,就创建一个Runnable匿名内部类对象,这个对象存入mTasks,在匿名内部类的run函数里面调用传入参数r.run()。然后通过一个scheduleNext函数把mTasks里面的所有对象通过THREAD_POOL_EXECUTOR.execute(mActive)执行一遍。说穿了,也就是说SerialExecutor类会把所有的任务丢入一个容器,之后把容器里面的所有对象一个一个的排队(串行化)执行THREAD_POOL_EXECUTOR.execute(mActive);
    image.png

    结果和进度的通知

    image.png

    和更新进度时我们会调用的publishProgress方法


    image.png
    image.png

    说明当子线程需要和UI线程进行通信时,其实就是通过这个handler,往UI线程发送消息。

    总结:

    1)、线程池的创建:
    在创建了AsyncTask的时候,会默认创建两个线程池SerialExecutor和ThreadPoolExecutor,SerialExecutor负责将任务串行化,ThreadPoolExecutor是真正执行任务的地方,且无论有多少个AsyncTask实例,两个线程池都会只有一份。
    2)、任务的执行:
    在execute中,会执行run方法,当执行完run方法后,会调用scheduleNext()不断的从双端队列中轮询,获取下一个任务并继续放到一个子线程中执行,直到异步任务执行完毕。
    3)、消息的处理:
    在执行完onPreExecute()方法之后,执行了doInBackground()方法,然后就不断的发送请求获取数据;在这个AsyncTask中维护了一个InternalHandler的类,这个类是继承Handler的,获取的数据是通过handler进行处理和发送的。在其handleMessage方法中,将消息传递给onProgressUpdate()进行进度的更新,也就可以将结果发送到主线程中,进行界面的更新了。
    4)、使用AsyncTask的注意点
    通过观察代码我们可以发现,每一个new出的AsyncTask只能执行一次execute()方法,多次运行将会报错

    相关文章

      网友评论

          本文标题:AyncTask源码解析

          本文链接:https://www.haomeiwen.com/subject/jreyghtx.html