【Android 异步操作】AsyncTask 异步任务 ( AsyncTask 异步任务执行方法 execute 方法相关源码解析 )
文章目录
- 一、AsyncTask 异步任务执行方法 execute() 引入
- 二、AsyncTask 异步任务执行方法 execute()
- 三、sDefaultExecutor 线程池解析
- 四、executeOnExecutor 方法解析
- 五、AsyncTask 异步任务执行方法 execute() 相关源码注释
一、AsyncTask 异步任务执行方法 execute() 引入
上一篇博客中 【Android 异步操作】AsyncTask 异步任务 ( 参数简介 | 方法简介 | 使用方法 | AsyncTask 源码分析 ) , 讲解了 AsyncTask<Params, Progress, Result> 异步任务的构造函数 ;
异步任务执行有两个方法 :
- 构造异步任务 : 调用 AsyncTask 的构造函数 , 创建 AsyncTask 异步任务对象 ;
- 执行异步任务 : 调用 AsyncTask 异步任务对象的 execute() 方法 , 执行异步任务 ;
本篇博客中讲解执行函数 AsyncTask<Params, Progress, Result> execute(Params… params) ;
// 1. 创建 AsyncTask 异步任务
MyAsyncTask mMyAsyncTask = new MyAsyncTask();// 2. 执行 AsyncTask 异步任务
mMyAsyncTask.execute();
二、AsyncTask 异步任务执行方法 execute()
AsyncTask<Params, Progress, Result> execute(Params… params) 方法作用 : AsyncTask 异步任务的 execute() 函数作用就是提交任务 , 其提交的任务就是 FutureTask , 其使用的是 线程池 提交任务 ;
① 参数 : 使用指定的参数 , 执行任务 ;
② 返回值 : 这个任务返回 AsyncTask<Params, Progress, Result> 本身对象 , 以便调用者可以持有该异步任务的引用 ;
③ 任务调度 : 该方法在队列上调度一个任务 , 该任务在一个单独的后台线程 , 或线程池中执行 ; 第一次引入后 , 异步任务在单独后台线程中被串行执行 ;
④ 不同版本的执行任务载体 :
- Android 1.6(API 级别 4)及以下的版本是在一个后台线程中串行执行 ;
- Android 2.0(API 级别 5)及以上的版本是在线程池中串行执行 ;
- Android 3.0(API 级别 11)及以上的版本有回复到在一个后台线程中串行执行 ;
在该类中 , 最终调用了 executeOnExecutor() 方法 , 使用 sDefaultExecutor 默认串行线程池执行任务 ;
public abstract class AsyncTask<Params, Progress, Result> {@MainThreadpublic final AsyncTask<Params, Progress, Result> execute(Params... params) {return executeOnExecutor(sDefaultExecutor, params);}
}
如果同时调用 AsyncTask 异步任务的 execute() 函数执行任务 , 其任务会逐个串行执行 , 不是并行的 ;
AsyncTask<Params, Progress, Result> 对象的 execute() 执行的任务是有序的 ;
三、sDefaultExecutor 线程池解析
上述执行异步任务的方法 executeOnExecutor() , 传入了 sDefaultExecutor 线程池作为参数 , 本节分析 sDefaultExecutor 线程池 ;
sDefaultExecutor 是成员变量 , 其声明类型是 Executor , 实际类型是自定义的线程池 SerialExecutor() ;
SerialExecutor 是一个线程池 , 执行任务 , 每次只执行一个任务 , 按照串行顺序执行 ; 该序列对于特定进程来说是全局的 , 即一个进程只有一个该序列 ;
在该线程池中 , 维护了如下两个成员 :
- 任务队列 ArrayDeque mTasks
- 当前执行任务 Runnable mActive
该线程池中 void execute(final Runnable r) 执行任务方法 :
- 执行当前传入的任务 : 自己创建一个 Runnable , 在其 run() 方法中执行传入的参数的 r 的 run() 方法 ;
- 执行下一个任务 : 执行完毕当前任务后 , 调用 scheduleNext() 执行下一个任务
scheduleNext() 方法 用于执行下一个任务 , 从队列中取出一个任务 , 如果取出的任务不为空 , 那么就执行该任务 ; 调用 SerialExecutor 类的 execute(final Runnable r) 方法执行该任务 ;
public abstract class AsyncTask<Params, Progress, Result> {private static final String LOG_TAG = "AsyncTask";/*** 自定义线程池 ; * 一个线程池 , 执行任务 , 每次只执行一个任务 , 按照串行顺序执行 ; * 该序列对于特定进程来说是全局的 , 即一个进程只有一个该序列 ; */public static final Executor SERIAL_EXECUTOR = new SerialExecutor();@UnsupportedAppUsageprivate static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;/*** 自定义线程池 ; * 一个线程池 , 执行任务 , 每次只执行一个任务 , 按照串行顺序执行 ; * 该序列对于特定进程来说是全局的 , 即一个进程只有一个该序列 ; */private static class SerialExecutor implements Executor {// 任务队列 final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();// 当前执行的任务 Runnable mActive;// 执行任务public synchronized void execute(final Runnable r) {// 自己创建一个 Runnable , 在其 run() 方法中执行如下方法 : // 传入的 execute(final Runnable r) 方法参数的 r 的 run() 方法 ; mTasks.offer(new Runnable() {public void run() {try {r.run();} finally {// 执行完毕当前任务后 , 执行下一个任务scheduleNext();}}});// 如果当前任务为空 , 那么执行下一个任务 if (mActive == null) {scheduleNext();}}/*** 执行下一个任务 * 从队列中取出一个任务 , 如果取出的任务不为空 , 那么就执行该任务 ; * 调用 SerialExecutor 类的 execute(final Runnable r) 方法执行该任务 ; */protected synchronized void scheduleNext() {if ((mActive = mTasks.poll()) != null) {// 执行队列中的任务的操作 THREAD_POOL_EXECUTOR.execute(mActive);}}}
}
四、executeOnExecutor 方法解析
executeOnExecutor 方法是异步任务执行的核心方法 ;
执行流程如下 :
① 判定合法性 : AsyncTask 异步任务只能执行一次 , 必须确保该 AsyncTask 异步任务没有执行过 , 如果执行过直接抛出异常 ;
② 设置运行状态 : 将该异步任务状态设置成 Status.RUNNING 状态 , 防止第二次被执行 ;
③ 主线程初始化 : 执行 onPreExecute() 方法 , 用户可以在该方法中初始化 UI , 该操作在 UI 主线程中运行 ;
④ 子线程后台任务执行 : 执行 FutureTask 中的 Callable 任务 , 也就是异步任务 , 该操作在子线程中运行 ;
public abstract class AsyncTask<Params, Progress, Result> { /*** 使用指定的参数 , 执行任务 ; * 这个任务返回 AsyncTask<Params, Progress, Result> 本身对象 , * 一遍调用者可以持有该异步任务的引用 ; * * 该方法通常与 THREAD_POOL_EXECUTOR 一同使用 , 允许多个任务在一个线程池中串行执行 , * 该线程池由 AsyncTask 异步任务管理 , 也可以使用自己的线程池定制相关行为 ; */@MainThreadpublic final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) {// 首先判定当前状态是否合法 , 确保该 AsyncTask 异步任务没有执行过 , // 每个 AsyncTask 异步任务创建后只能执行一次 ; if (mStatus != Status.PENDING) {switch (mStatus) {case RUNNING:throw new IllegalStateException("Cannot execute task:"+ " the task is already running.");case FINISHED:throw new IllegalStateException("Cannot execute task:"+ " the task has already been executed "+ "(a task can be executed only once)");}}// 设置状态为执行状态 mStatus = Status.RUNNING;// 执行 doInBackground() 之前执行的方法 onPreExecute();// 设置 WorkerRunnable 的 Params[] mParams 参数mWorker.mParams = params;// 执行 FutureTask 中的 Callable 任务exec.execute(mFuture);return this;}}
五、AsyncTask 异步任务执行方法 execute() 相关源码注释
public abstract class AsyncTask<Params, Progress, Result> {private static final String LOG_TAG = "AsyncTask";/*** 自定义线程池 ; * 一个线程池 , 执行任务 , 每次只执行一个任务 , 按照串行顺序执行 ; * 该序列对于特定进程来说是全局的 , 即一个进程只有一个该序列 ; */public static final Executor SERIAL_EXECUTOR = new SerialExecutor();@UnsupportedAppUsageprivate static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;/*** 自定义线程池 ; * 一个线程池 , 执行任务 , 每次只执行一个任务 , 按照串行顺序执行 ; * 该序列对于特定进程来说是全局的 , 即一个进程只有一个该序列 ; */private static class SerialExecutor implements Executor {// 任务队列 final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();// 当前执行的任务 Runnable mActive;// 执行任务public synchronized void execute(final Runnable r) {// 自己创建一个 Runnable , 在其 run() 方法中执行如下方法 : // 传入的 execute(final Runnable r) 方法参数的 r 的 run() 方法 ; mTasks.offer(new Runnable() {public void run() {try {r.run();} finally {// 执行完毕当前任务后 , 执行下一个任务scheduleNext();}}});// 如果当前任务为空 , 那么执行下一个任务 if (mActive == null) {scheduleNext();}}/*** 执行下一个任务 * 从队列中取出一个任务 , 如果取出的任务不为空 , 那么就执行该任务 ; * 调用 SerialExecutor 类的 execute(final Runnable r) 方法执行该任务 ; */protected synchronized void scheduleNext() {if ((mActive = mTasks.poll()) != null) {// 执行队列中的任务的操作 THREAD_POOL_EXECUTOR.execute(mActive);}}}/*** 使用指定的参数 , 执行任务 ; * 这个任务返回 AsyncTask<Params, Progress, Result> 本身对象 , * 一遍调用者可以持有该异步任务的引用 ; * * 该方法在队列上调度一个任务 , 该任务在一个单独的后台线程 , 或线程池中执行 ; * 第一次引入后 , 异步任务在单独后台线程中被串行执行 ; * Android 1.6(API 级别 4)及以下的版本是在一个后台线程中串行执行 ; * Android 2.0(API 级别 5)及以上的版本是在线程池中串行执行 ; * Android 3.0(API 级别 11)及以上的版本有回复到在一个后台线程中串行执行 ; ** <p>改方法必须在 UI 线程中调用 ** @param 要执行的任务的参数.** @return 返回异步任务 AsyncTask 本身 .*/@MainThreadpublic final AsyncTask<Params, Progress, Result> execute(Params... params) {return executeOnExecutor(sDefaultExecutor, params);}/*** 使用指定的参数 , 执行任务 ; * 这个任务返回 AsyncTask<Params, Progress, Result> 本身对象 , * 一遍调用者可以持有该异步任务的引用 ; * * 该方法通常与 THREAD_POOL_EXECUTOR 一同使用 , 允许多个任务在一个线程池中串行执行 , * 该线程池由 AsyncTask 异步任务管理 , 也可以使用自己的线程池定制相关行为 ; */@MainThreadpublic final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) {// 首先判定当前状态是否合法 , 确保该 AsyncTask 异步任务没有执行过 , // 每个 AsyncTask 异步任务创建后只能执行一次 ; if (mStatus != Status.PENDING) {switch (mStatus) {case RUNNING:throw new IllegalStateException("Cannot execute task:"+ " the task is already running.");case FINISHED:throw new IllegalStateException("Cannot execute task:"+ " the task has already been executed "+ "(a task can be executed only once)");}}// 设置状态为执行状态 mStatus = Status.RUNNING;// 执行 doInBackground() 之前执行的方法 onPreExecute();// 设置 WorkerRunnable 的 Params[] mParams 参数mWorker.mParams = params;// 执行 FutureTask 中的 Callable 任务exec.execute(mFuture);return this;}}
【Android 异步操作】AsyncTask 异步任务 ( AsyncTask 异步任务执行方法 execute 方法相关源码解析 )相关推荐
- Android 异步消息处理机制(Handler 、 Looper 、MessageQueue)源码解析
1.Handler的由来 当程序第一次启动的时候,Android会同时启动一条主线程( Main Thread)来负责处理与UI相关的事件,我们叫做UI线程. Android的UI操作并不是线程安全的 ...
- 【Android 插件化】Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 一 | Activity 进程相关源码 )
Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...
- Android之AsyncTask源码解析
转载请标明出处:[顾林海的博客] 个人开发的微信小程序,目前功能是书籍推荐,后续会完善一些新功能,希望大家多多支持! ##前言 AsyncTask是一种轻量级的异步任务类,内部封装了Thread和Ha ...
- AsyncTask、HandlerThread、IntentSerivce源码解析
在进行耗时操作时,一般new Thread().start();开启一个子线程,然后通过handler消息去更新ui(关于handler可以看这里:android Handler.Looper.Mes ...
- AsyncTask源码解析,你需要摸清的细节
AsyncTask简介 1. AsyncTask提供了一种恰当的简单的跟UI Thread交互的方式. 2. 它不需要通过操控Threads或Handler就可以将后台操作以及其结果展示在UI Thr ...
- Redux异步解决方案之Redux-Thunk原理及源码解析
前段时间,我们写了一篇Redux源码分析的文章,也分析了跟React连接的库React-Redux的源码实现.但是在Redux的生态中还有一个很重要的部分没有涉及到,那就是Redux的异步解决方案.本 ...
- 【Android 异步操作】线程池 ( 线程池作用 | 线程池种类 | 线程池工作机制 | 线程池任务调度源码解析 )
文章目录 一.线程池作用 二.线程池种类 三.线程池工作机制 四.线程池任务调度源码解析 一.线程池作用 线程池作用 : ① 避免创建线程 : 避免每次使用线程时 , 都需要 创建线程对象 ; ② 统 ...
- Spring5源码 - 12 Spring事件监听机制_异步事件监听应用及源码解析
文章目录 Pre 实现原理 应用 配置类 Event事件 事件监听 EventListener 发布事件 publishEvent 源码解析 (反推) Spring默认的事件广播器 SimpleApp ...
- Android多线程之IntentService源码解析
想要了解 IntentService 的工作原理需要先对 Android 系统中以 Handler.Looper.MessageQueue 组成的异步消息处理机制以及 HandlerThread 有所 ...
最新文章
- Android开发将List转化为JsonArray和JsonObject
- Node.js权威指南 (7) - 实现基于TCP与UDP的数据通信
- Centos7编译安装nginx并设置反向代理
- 第三次学JAVA再学不好就吃翔(part73)--SimpleDateFormat类
- Tomcat 服务自动启动
- bzoj4171: Rhl的游戏
- C++基础:第七章 函数
- WPF中的Application类。
- scala下载新的版本号
- 三维虚拟工厂仿真交互展示有哪些功能
- 关于修复msvcp110.dll丢失的问题
- 统计学基础--假设检验
- NFormer: robust person re-identification with neighbor transformer
- bazel 链接第三方动态库_谷歌携手OPPO共同开发CameraX技术,第三方拍照应用有福了...
- easypoi.excel 导入不固定的合并单元格数据
- 【ORB-SLAM】原理部分
- cad旋转命令_如何将CAD图形旋转至水平位置?
- Tian Ji -- The Horse Racing 贪心算法
- python怎么编辑程序_少儿编程:Python系列24——字符串的替换和检索
- 安装安卓(Android)x86系统