当前位置: 首页 > news >正文

AsyncTask使用及源码查看Android P

AsyncTask

AsyncTask用于处理耗时任务,可以即时通知进度,最终返回结果。可以用于下载等处理。

使用

实现类继承三个方法

1. doInBackground后台执行,在此方法中进行延时操作

    /*** Override this method to perform a computation on a background thread. The* specified parameters are the parameters passed to {@link #execute}* by the caller of this task.** This method can call {@link #publishProgress} to publish updates* on the UI thread.** @param params The parameters of the task.** @return A result, defined by the subclass of this task.** @see #onPreExecute()* @see #onPostExecute* @see #publishProgress*/@WorkerThreadprotected abstract Result doInBackground(Params... params);

2. onProgressUpdate刷新UI

    /*** Runs on the UI thread after {@link #publishProgress} is invoked.* The specified values are the values passed to {@link #publishProgress}.** @param values The values indicating progress.** @see #publishProgress* @see #doInBackground*/@SuppressWarnings({"UnusedDeclaration"})@MainThreadprotected void onProgressUpdate(Progress... values){}

3. onPostExecute结果返回,此结果即为后台执行方法返回的结果。

    /*** <p>Runs on the UI thread after {@link #doInBackground}. The* specified result is the value returned by {@link #doInBackground}.</p>* * <p>This method won't be invoked if the task was cancelled.</p>** @param result The result of the operation computed by {@link #doInBackground}.** @see #onPreExecute* @see #doInBackground* @see #onCancelled(Object) */@SuppressWarnings({"UnusedDeclaration"})@MainThreadprotected void onPostExecute(Result result) {}

Result,Progress,Params三者是AsyncTask的泛型,从代码可以看出,Result为返回结果类型,Progress是刷新进度的类型,Params是处理耗时任务时需要传入的类型。

public abstract class AsyncTask<Params, Progress, Result>

4. execute启动方法

    /*** Executes the task with the specified parameters. The task returns* itself (this) so that the caller can keep a reference to it.* * <p>Note: this function schedules the task on a queue for a single background* thread or pool of threads depending on the platform version.  When first* introduced, AsyncTasks were executed serially on a single background thread.* Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed* to a pool of threads allowing multiple tasks to operate in parallel. Starting* {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are back to being* executed on a single thread to avoid common application errors caused* by parallel execution.  If you truly want parallel execution, you can use* the {@link #executeOnExecutor} version of this method* with {@link #THREAD_POOL_EXECUTOR}; however, see commentary there for warnings* on its use.** <p>This method must be invoked on the UI thread.** @param params The parameters of the task.** @return This instance of AsyncTask.** @throws IllegalStateException If {@link #getStatus()} returns either*         {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.** @see #executeOnExecutor(java.util.concurrent.Executor, Object[])* @see #execute(Runnable)*/@MainThreadpublic final AsyncTask<Params, Progress, Result> execute(Params... params) {return executeOnExecutor(sDefaultExecutor, params);}

分析

相关知识点:

  • 线程池
  • Android Handler

1. 构造器

   /*** Creates a new asynchronous task. This constructor must be invoked on the UI thread.*/public AsyncTask() {this((Looper) null);}/*** Creates a new asynchronous task. This constructor must be invoked on the UI thread.** @hide*/public AsyncTask(@Nullable Handler handler) {this(handler != null ? handler.getLooper() : null);}/*** Creates a new asynchronous task. This constructor must be invoked on the UI thread.** @hide*/public AsyncTask(@Nullable Looper callbackLooper) {mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()? getMainHandler(): new Handler(callbackLooper);mWorker = new WorkerRunnable<Params, Result>() {public Result call() throws Exception {mTaskInvoked.set(true);Result result = null;try {Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);//noinspection uncheckedresult = doInBackground(mParams);Binder.flushPendingCommands();} catch (Throwable tr) {mCancelled.set(true);throw tr;} finally {postResult(result);}return result;}};mFuture = new FutureTask<Result>(mWorker) {@Overrideprotected void done() {try {postResultIfNotInvoked(get());} catch (InterruptedException e) {android.util.Log.w(LOG_TAG, e);} catch (ExecutionException e) {throw new RuntimeException("An error occurred while executing doInBackground()",e.getCause());} catch (CancellationException e) {postResultIfNotInvoked(null);}}};}

1.1 Handler

使用getMainHandler()返回的Handler。消息处理部分可以看到完成处理与进度更新。

    private static Handler getMainHandler() {synchronized (AsyncTask.class) {if (sHandler == null) {sHandler = new InternalHandler(Looper.getMainLooper());}return sHandler;}}private static class InternalHandler extends Handler {public InternalHandler(Looper looper) {super(looper);}@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})@Overridepublic void handleMessage(Message msg) {AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;switch (msg.what) {case MESSAGE_POST_RESULT:// There is only one resultresult.mTask.finish(result.mData[0]);break;case MESSAGE_POST_PROGRESS:result.mTask.onProgressUpdate(result.mData);break;}}}private void finish(Result result) {if (isCancelled()) {onCancelled(result);} else {onPostExecute(result);}mStatus = Status.FINISHED;}@SuppressWarnings({"UnusedDeclaration"})@MainThreadprotected void onProgressUpdate(Progress... values) {}

1.2 WorkerRunnable实现对象mWorker

使用Callable接口。

    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {Params[] mParams;}

1.3 FutureTask实现对象 mFuture

FutureTask其中保存了Callable接口。

    public FutureTask(Callable<V> var1) {if (var1 == null) {throw new NullPointerException();} else {this.callable = var1;this.state = 0;}}

2. exectue执行操作开始

    @MainThreadpublic final AsyncTask<Params, Progress, Result> execute(Params... params) {return executeOnExecutor(sDefaultExecutor, params);}/*** Executes the task with the specified parameters. The task returns* itself (this) so that the caller can keep a reference to it.* * <p>This method is typically used with {@link #THREAD_POOL_EXECUTOR} to* allow multiple tasks to run in parallel on a pool of threads managed by* AsyncTask, however you can also use your own {@link Executor} for custom* behavior.* * <p><em>Warning:</em> Allowing multiple tasks to run in parallel from* a thread pool is generally <em>not</em> what one wants, because the order* of their operation is not defined.  For example, if these tasks are used* to modify any state in common (such as writing a file due to a button click),* there are no guarantees on the order of the modifications.* Without careful work it is possible in rare cases for the newer version* of the data to be over-written by an older one, leading to obscure data* loss and stability issues.  Such changes are best* executed in serial; to guarantee such work is serialized regardless of* platform version you can use this function with {@link #SERIAL_EXECUTOR}.** <p>This method must be invoked on the UI thread.** @param exec The executor to use.  {@link #THREAD_POOL_EXECUTOR} is available as a*              convenient process-wide thread pool for tasks that are loosely coupled.* @param params The parameters of the task.** @return This instance of AsyncTask.** @throws IllegalStateException If {@link #getStatus()} returns either*         {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.** @see #execute(Object[])*/@MainThreadpublic final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) {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;onPreExecute();mWorker.mParams = params;exec.execute(mFuture);return this;}

2.1 进行status判断:

  1. 正在运行的对象调用此方法会抛出异常,正在运行的设置在此方法中。
  2. 已经完成的对象调用此方法会抛出异常,已经完成的设置在InternalHandler中调用。
    private void finish(Result result) {if (isCancelled()) {onCancelled(result);} else {onPostExecute(result);}mStatus = Status.FINISHED;}

2.2 调用onPreExecte()方法

子类实现此方法会在耗时操作前执行一些操作。

    /*** Runs on the UI thread before {@link #doInBackground}.** @see #onPostExecute* @see #doInBackground*/@MainThreadprotected void onPreExecute() {}

2.3 执行exec.execute(mFuture)

2.3.1 exec是什么?

通过调用链可看出是sDefaultExecutor。在代码中可以看到是SerialExecutor静态内部类对象。

    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();private static final int MESSAGE_POST_RESULT = 0x1;private static final int MESSAGE_POST_PROGRESS = 0x2;private 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) {mTasks.offer(new Runnable() {public void run() {try {r.run();} finally {scheduleNext();}}});if (mActive == null) {scheduleNext();}}protected synchronized void scheduleNext() {if ((mActive = mTasks.poll()) != null) {THREAD_POOL_EXECUTOR.execute(mActive);}}}
2.3.2 execute(final Runnable r)传是mFuture这里是Runnable
public class FutureTask<V> implements RunnableFuture<V>{}
public interface RunnableFuture<V> extends Runnable, Future<V> {void run();
}
2.3.3 调用mFuture的run方法

刚才1.3futuretask实现对象-mfuture可以看出
this.callable = var1;,即此处调用了mWorker的call()方法

 public void run() {if (this.state == 0 && UNSAFE.compareAndSwapObject(this, runnerOffset, (Object)null, Thread.currentThread())) {boolean var9 = false;try {var9 = true;Callable var1 = this.callable;if (var1 != null) {if (this.state == 0) {Object var2;boolean var3;try {var2 = var1.call();var3 = true;}....}....}....}....}}
2.3.4 mWorker调用doInBackground
        mWorker = new WorkerRunnable<Params, Result>() {public Result call() throws Exception {mTaskInvoked.set(true);Result result = null;try {Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);//noinspection uncheckedresult = doInBackground(mParams);Binder.flushPendingCommands();} catch (Throwable tr) {mCancelled.set(true);throw tr;} finally {postResult(result);}return result;}};
2.3.5 doInBackground返回result,调用postResult(result)

这里发送了结果,见1.1处理

    private Result postResult(Result result) {@SuppressWarnings("unchecked")Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,new AsyncTaskResult<Result>(this, result));message.sendToTarget();return result;}

3. 进度刷新

进度刷新可以调用如下方法。大多在doInBackground中使用。

    /*** This method can be invoked from {@link #doInBackground} to* publish updates on the UI thread while the background computation is* still running. Each call to this method will trigger the execution of* {@link #onProgressUpdate} on the UI thread.** {@link #onProgressUpdate} will not be called if the task has been* canceled.** @param values The progress values to update the UI with.** @see #onProgressUpdate* @see #doInBackground*/@WorkerThreadprotected final void publishProgress(Progress... values) {if (!isCancelled()) {getHandler().obtainMessage(MESSAGE_POST_PROGRESS,new AsyncTaskResult<Progress>(this, values)).sendToTarget();}}

4. 如何暂停/取消

直接在doInBackground方法中返回Result即可,Result是泛型,可以自定义各种类型的返回值。

相关文章:

AsyncTask使用及源码查看Android P

AsyncTask AsyncTask用于处理耗时任务&#xff0c;可以即时通知进度&#xff0c;最终返回结果。可以用于下载等处理。 使用 实现类继承三个方法 1. doInBackground后台执行&#xff0c;在此方法中进行延时操作 /*** Override this method to perform a computation on a back…...

花2个月面过华为测开岗,拿个30K不过分吧?

背景介绍 美本计算机专业&#xff0c;代码能力一般&#xff0c;之前有过两段实习以及一个学校项目经历。第一份实习是大二暑期在深圳的一家互联网公司做前端开发&#xff0c;第二份实习由于大三暑假回国的时间比较短&#xff08;小于两个月&#xff09;&#xff0c;于是找的实…...

JAVA练习51-最大子数组和

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、题目-最大子数组和 1.题目描述 2.思路与代码 2.1 思路 2.2 代码 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 2月15日练…...

Inception Transformer

paper链接: https://arxiv.org/abs/2205.12956v2 code链接: https://github.com/sail-sg/iFormer Inception Transformer一、引言二、实现细节三、实验一、分类二、检测三、分割四、消融实验一、引言 最近的研究表明&#xff0c;Transformer具有很强的建立远程依赖关系的能力…...

10分钟学会数据库压力测试,你敢信?

目录 前言 查看数据库版本 下载驱动&#xff1a; 菜单路径 配置 Variable Name Bound to Pool模块配置 Connection pool configuration模块配置 Database Connection Configuration模块配置 菜单路径 Variable Name Bound to Pool 脚本结构 脚本&#xff08;执行查询…...

论文阅读 | Video Super-Resolution Transformer

引言&#xff1a;2021年用Transformer实现视频超分VSR的文章&#xff0c;改进了SA并在FFN中加入了光流引导 论文&#xff1a;【here】 代码&#xff1a;【here】 Video Super-Resolution Transformer 引言 视频超分中有一组待超分的图片&#xff0c;因此视频超分也经常被看做…...

7-6 带头节点的双向循环链表操作

本题目要求读入一系列整数&#xff0c;依次插入到双向循环链表的头部和尾部&#xff0c;然后顺序和逆序输出链表。 链表节点类型可以定义为 typedef int DataType; typedef struct LinkedNode{DataType data;struct LinkedNode *prev;struct LinkedNode *next; }LinkedNode;链…...

npm publish 、 npm adduser 提示 403 的问题

0. 查看使用的源&#xff1a;npm config get registry1. 如果使用的不是官方的源&#xff0c;切换&#xff1a;npm config set registry https://registry.npmjs.org/2. 登录&#xff1a;npm adduser3. 查看是否登录成功&#xff1a;npm whoami4. 执行发布命令&#xff1a;npm …...

Java 8的函数式接口使用示例

什么是函数式接口 有且只有一个抽象方法的接口被称为函数式接口&#xff0c;函数式接口适用于函数式编程的场景&#xff0c;Lambda就是Java中函数式编程的体现&#xff0c;可以使用Lambda表达式创建一个函数式接口的对象&#xff0c;一定要确保接口中有且只有一个抽象方法&…...

2023年企业如何改善员工体验?为什么员工体验很重要?

什么是员工体验&#xff1f;大约 96% 的企业领导者表示&#xff0c;专注于员工体验可以更轻松地留住顶尖人才。[1] 这还不是全部。令人震惊的是&#xff0c;87%的企业领导者还表示&#xff0c;优先考虑员工的幸福感将给他们带来竞争优势。尽管有这些发现&#xff0c;但只有19%的…...

设计模式:桥接模式让抽象和实现解耦,各自独立变化

一、问题场景 现在对”不同手机类型“的 “不同品牌”实现操作编程(比如: 开机、关机、上网&#xff0c;打电话等) 二、传统解决方案 传统方案解决手机使用问题类图&#xff1a; 三、传统方案分析 传统方案解决手机操作问题分析 1、扩展性问题(类爆炸)&#xff0c;如果我们…...

C++学习记录——십 STL初级认识、标准库string类

文章目录1、什么是STL2、STL简介3、什么是string类4、string类的常用接口说明1、常见构造函数2、容量操作3、迭代器4、其他的标准库的string类关于string类的内容&#xff0c;可以在cplusplus.com查看到。 1、什么是STL STL是C标准库的重要组成部分&#xff0c;不仅是一个可复…...

【redis】redis缓存与数据库的一致性

【redis】redis缓存与数据库的一致性【1】四种同步策略【2】更新缓存还是删除缓存&#xff08;1&#xff09;更新缓存&#xff08;2&#xff09;删除缓存【3】先更新数据库还是先删除缓存&#xff08;1&#xff09;出现失败时候的情况1-先删除缓存&#xff0c;再更新数据库&…...

XCP实战系列介绍12-基于Vector_Davinci工具的XCP配置介绍(一)

本文框架 1.概述2. EcuC配置2.1 Pdu添加步骤2.2 配置项说明3. Can 模块配置4. CanIf 模块配置4.1 接收帧的Hardware Receive Object配置4.2 接收帧和发送帧的Pdu配置1.概述 在文章《看了就会的XCP协议介绍》中详细介绍了XCP的协议,在《XCP实战系列介绍01-测量与标定底层逻辑》…...

Unity Material详解

一、创建 二、属性 1.Shader:Unity内置了一些shader&#xff0c;用户自定义的shader也在这里出现. Edit: 可以编辑一些shader可编辑的内容&#xff0c;如一些属性. 2.Rendering Mode:渲染模式 Opaque-不透明-石头适用于所有的不透明的物体Cutout-镂空-破布透明度只有0%和100…...

碰撞检测算法分类

包围形法粗糙检测, 包含以下两种类检测外接圆法轴对齐包围矩形&#xff0c; AABB 碰撞检测算法之包围形法分离轴精细检测 BOX vs PolygonOBBseparating Axis Theorem碰撞检测算法之分离轴定理GJKGJK&#xff08;Gilbert–Johnson–Keerthi&#xff09;, 相比 SAT 算法&#xff…...

代码随想录第十二天(

文章目录232. 用栈实现队列补充知识——Deque232. 用栈实现队列 答案思路&#xff1a; 在push数据的时候&#xff0c;只要数据放进输入栈就好&#xff0c;但在pop的时候&#xff0c;操作就复杂一些&#xff0c;输出栈如果为空&#xff0c;就把进栈数据全部导入进来&#xff0…...

电源模块 DC-DC直流升压正负高压输出12v24v转±110V±150V±220V±250V±300V±600V

特点效率高达80%以上1*2英寸标准封装电源正负双输出稳压输出工作温度: -40℃~85℃阻燃封装&#xff0c;满足UL94-V0 要求温度特性好可直接焊在PCB 上应用HRA 1~40W系列模块电源是一种DC-DC升压变换器。该模块电源的输入电压分为&#xff1a;4.5~9V、9~18V、及18~36VDC标准&…...

【动画图解】这个值取对了,ViewPager2才能纵享丝滑

前言 在前两篇文章中&#xff0c;我们通过一张张清晰明了的「示意图」&#xff0c;详细地复盘了RecyclerView「缓存复用机制」与「预拉取机制」的工作流程&#xff0c;这种「图解」创作形式也得到了来自不同平台读者们的一致认可。 而从本文开始&#xff0c;我们将正式进入Vi…...

CSDN每日一练:小豚鼠搬家

题目名称&#xff1a;小豚鼠搬家 时间限制&#xff1a;1000ms内存限制&#xff1a;256M 题目描述 小豚鼠排排坐。 小艺酱买了一排排格子的小房子n*m&#xff0c;她想让k只小豚鼠每只小豚鼠都有自己的房子。 但是为了不浪费空间&#xff0c;她想要小房子的最外圈尽量每行每列都有…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

comfyui 工作流中 图生视频 如何增加视频的长度到5秒

comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗&#xff1f; 在ComfyUI中实现图生视频并延长到5秒&#xff0c;需要结合多个扩展和技巧。以下是完整解决方案&#xff1a; 核心工作流配置&#xff08;24fps下5秒120帧&#xff09; #mermaid-svg-yP…...

webpack面试题

面试题&#xff1a;webpack介绍和简单使用 一、webpack&#xff08;模块化打包工具&#xff09;1. webpack是把项目当作一个整体&#xff0c;通过给定的一个主文件&#xff0c;webpack将从这个主文件开始找到你项目当中的所有依赖文件&#xff0c;使用loaders来处理它们&#x…...

字符串哈希+KMP

P10468 兔子与兔子 #include<bits/stdc.h> using namespace std; typedef unsigned long long ull; const int N 1000010; ull a[N], pw[N]; int n; ull gethash(int l, int r){return a[r] - a[l - 1] * pw[r - l 1]; } signed main(){ios::sync_with_stdio(false), …...