Android异步4:深入AsyncTask原理

AsyncTask的本质是一个线程池,所有提交的异步任务都会在这个线程池(想想C3P0)中的工作线程内执行,当工作线程需要跟UI线程交互时,工作线程会通过向在UI线程创建的Handler传递消息的方式,调用相关的回调函数,从而实现UI界面的更新。

还是以昨天的例子为例~来说明AsyncTask的实现原理

package cn.caiwb.aysnc;


import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Toast;

public class AsyncTaskActivity extends Activity {

private ImageView mImageView;
private Button mButton;
private ProgressBar mProgressBar;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

mImageView= (ImageView) findViewById(R.id.imageView);
mButton = (Button) findViewById(R.id.button);
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mButton.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
GetIteyeLogoTask task = new GetIteyeLogoTask();
task.execute("http://www.iteye.com/images/logo.gif");
}
});
}

class GetIteyeLogoTask extends AsyncTask<String,Integer,Bitmap> {//继承AsyncTask

@Override
protected Bitmap doInBackground(String... params) {//处理后台执行的任务,在后台线程执行
publishProgress(0);//将会调用onProgressUpdate(Integer... progress)方法
HttpClient hc = new DefaultHttpClient();
publishProgress(30);
HttpGet hg = new HttpGet(params[0]);//获取csdn的logo
final Bitmap bm;
try {
HttpResponse hr = hc.execute(hg);
bm = BitmapFactory.decodeStream(hr.getEntity().getContent());
} catch (Exception e) {

return null;
}
publishProgress(100);
//mImageView.setImageBitmap(result); 不能在后台线程操作ui
return bm;
}

protected void onProgressUpdate(Integer... progress) {//在调用publishProgress之后被调用,在ui线程执行
mProgressBar.setProgress(progress[0]);//更新进度条的进度
}

protected void onPostExecute(Bitmap result) {//后台任务执行完之后被调用,在ui线程执行
if(result != null) {
Toast.makeText(AsyncTaskActivity.this, "成功获取图片", Toast.LENGTH_LONG).show();
mImageView.setImageBitmap(result);
}else {
Toast.makeText(AsyncTaskActivity.this, "获取图片失败", Toast.LENGTH_LONG).show();
}
}

protected void onPreExecute () {//在 doInBackground(Params...)之前被调用,在ui线程执行
mImageView.setImageBitmap(null);
mProgressBar.setProgress(0);//进度条复位
}

protected void onCancelled () {//在ui线程执行
mProgressBar.setProgress(0);//进度条复位
}

}


}


分析:

在分析实现流程之前,我们先了解一下AsyncTask有哪些成员变量。


private static final int CORE_POOL_SIZE =5;//5个核心工作线程
private static final int MAXIMUM_POOL_SIZE = 128;//最多128个工作线程
private static final int KEEP_ALIVE = 1;//空闲线程的超时时间为1秒

private static final BlockingQueue<Runnable> sWorkQueue =
new LinkedBlockingQueue<Runnable>(10);//等待队列

private static final ThreadPoolExecutorsExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue,sThreadFactory);//线程池是静态变量,所有的异步任务都会放到这个线程池的工作线程内执行。



回到例子中,点击按钮之后会新建一个GetIteyeLogoTask对象:


GetIteyeLogoTask task = new GetIteyeLogoTask();


此时会调用父类AsyncTask的构造函数:

AsyncTask.java


public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return doInBackground(mParams);
}
};

mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
Message message;
Result result = null;

try {
result = get();
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));
message.sendToTarget();//取消任务,发送MESSAGE_POST_CANCEL消息
return;
} catch (Throwable t) {
throw new RuntimeException("An error occured while executing "
+ "doInBackground()", t);
}

message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(AsyncTask.this, result));//完成任务,发送MESSAGE_POST_RESULT消息并传递result对象
message.sendToTarget();
}
};
}



WorkerRunnable类实现了callable接口的call()方法,该函数会调用我们在AsyncTask子类中实现的doInBackground(mParams)方法,由此可见,WorkerRunnable封装了我们要执行的异步任务。FutureTask中的protected void done() {}方法实现了异步任务状态改变后的操作。当异步任务被取消,会向UI线程传递MESSAGE_POST_CANCEL消息,当任务成功执行,会向UI线程传递MESSAGE_POST_RESULT消息,并把执行结果传递到UI线程。

由此可知,AsyncTask在构造的时候已经定义好要异步执行的方法doInBackground(mParams)和任务状态变化后的操作(包括失败和成功)。

当创建完GetIteyeLogoTask对象后,执行


task.execute("http://www.iteye.com/images/logo.gif");


此时会调用AsyncTask的execute(Params...params)方法


public final AsyncTask<Params,Progress, Result> execute(Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw newIllegalStateException("Cannot execute task:"
+ " the taskis already running.");
case FINISHED:
throw newIllegalStateException("Cannot execute task:"
+ " the taskhas already been executed "
+ "(a task canbe executed only once)");
}
}

mStatus = Status.RUNNING;

onPreExecute();//运行在ui线程,在提交任务到线程池之前执行

mWorker.mParams = params;
sExecutor.execute(mFuture);//提交任务到线程池

return this;
}


当任务正在执行或者已经完成,会抛出IllegalStateException,由此可知我们不能够重复调用execute(Params...params)方法。在提交任务到线程池之前,调用了onPreExecute()方法。然后才执行sExecutor.execute(mFuture)是任务提交到线程池。

前面我们说到,当任务的状态发生改变时(1、执行成功2、取消执行3、进度更新),工作线程会向UI线程的Handler传递消息。我们知道Handler要处理其他线程传递过来的消息。在AsyncTask中,InternalHandler是在UI线程上创建的,它接收来自工作线程的消息,实现代码如下:


private static class InternalHandler extends Handler {
@SuppressWarnings({"unchecked","RawUseOfParameterizedType"})
@Override
public voidhandleMessage(Message msg) {
AsyncTaskResult result =(AsyncTaskResult) msg.obj;
switch (msg.what) {
caseMESSAGE_POST_RESULT:
// There is onlyone result
result.mTask.finish(result.mData[0]);//执行任务成功
break;
caseMESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);//进度更新
break;
caseMESSAGE_POST_CANCEL:
result.mTask.onCancelled();//取消任务
break;
}
}
}


当接收到消息之后,AsyncTask会调用自身相应的回调方法。

[b]总结:[/b]

1、 AsyncTask的本质是一个静态的线程池,AsyncTask派生出的子类可以实现不同的异步任务,这些任务都是提交到静态的线程池中执行。

2、线程池中的工作线程执行doInBackground(mParams)方法执行异步任务

3、当任务状态改变之后,工作线程会向UI线程发送消息,AsyncTask内部的InternalHandler响应这些消息,并调用相关的回调函数
Android异步任务AsyncTask原理(基于Android9.0) AsyncTask原理前言AsyncTask介绍源码分析 前言 在Android开发中经常会通过线程去执行耗时的任务,并且在任务执行完之后通常会用到Handler来更新UI。虽然实现简单,但是有多个任务同时执行时则会显得代码很臃肿。Android提供了AsyncTask,它使得异步任务实现起来更加简单,代码更简洁。 AsyncTask介绍 AsyncTask是一个抽象的泛型类,它有3个泛型参数,分... 阅读详情

相关推荐

深入浅出AsyncTask的工作原理

前言 AsyncTask类一般是android开发人员接触的最早的异步处理方法,虽然现在流行的有很多新的异步任务类,如RxJava等,但是对于AsyncTask的底层实现原理还是有必要了解学习的,对于我们自己理解其他框架或者自己设计框架都有很大的帮助。它使用handler和线程池的方式打到异步操作,将结果返回到主线程处理。 数据结构 在讲解AsyncTask的原理前,我们需要先来复习或者学习下其用到的数据结构。这些是我们必须要了解的数据结构。 Executor: 查看如下注释和中文解释,可以了解其实现即可以是串行执行也可以顺序执行,完全取决于使用了什么类型的执行器。更多细节解释可以查看JDK源

详解AsyncTask实现原理

AsyncTask允许执行后台计算并将计算结果发送给UI线程,过程中无需显示地借助Handler等。这是因为AsyncTask内部封装了线程池用于执行后台计算,并通过Handler将结果传递给UI线程。 根据AsyncTask的定义可知,主要包含三个参数,分别代表:参数类型、后台任务执行的进度类型、返回的结果类型。若不需要某个参数,可直接设为Void类型即可。 public abstrac

AudreyShen的博客 556

2024高校网络安全管理运维赛题目--复现+题目+wp

官方writeup集思广益比较好的备份。

书山有路勤为径,学海无涯苦作舟 1323

AsyncTask 内部实现机制

在 Android 应用开发的过程中,我们需要时刻注意保证应用程序的稳定和 UI 操作响应及时,因为不稳定或响应缓慢的应用将给应用带来不好的印象,严重的用户卸载你的APP,这样你的努力就没有体现的价值了。本文试图从 AsyncTask 的作用说起,进一步的讲解一下内部的实现机制。如果有一些开发经验的人,读完之后应该对使用 AsnycTask 过程中的一些问题豁然开朗,开发经验不丰富的也可以从中找到

安卓开发 646

数字经济新质生产力数字化转型数据要素流通交易解决方案:数据要素化演进路径与管理、公共数据授权运营平台体系、数据底座、典型应用场景

数字经济的发展依赖于数据要素的有效流通与交易,数字化转型的核心在于数据的全生命周期管理和价值释放。数据要素化通过数据资源化、资产化和资本化的“三化”过程,实现其经济与社会价值。数据管理涵盖采集、存储、加工、分析等环节,支持数据的度量与交换。公共数据、企业数据和个人数据通过场内、场外及二级市场交易实现资本化。公共数据开发利用面临隐私泄露、监督管理难等痛点,目标是构建授权运营平台体系,确保数据流通的安全与效率。平台体系包括统一门户、授权管理、运营管理、合规监督等核心功能,支持明文、密文和可信交换流通方式。数据底

weixin_44094929的博客 1003

中兴畅行60 ZTE 7552N 深度改造指南:从解锁BL到Magisk Root与IMEI硬改全流程

本文详细介绍了中兴畅行60(ZTE 7552N)的深度改造全流程,包括解锁BL、刷入Magisk获取Root权限以及IMEI硬改等关键步骤。通过专业的操作指南和实用技巧,帮助用户安全完成设备改造,同时提醒注意法律风险和技术难点。

weixin_33670786的博客 1900

AsyncTask原理详解!

在项目中子线程和UI线程交互过程中,经常会用到AsyncTask,AsyncTask使用场景有网络访问、上传文件等。 AsyncTask的核心原理有以下几条,请配合后面详解来理解。 1、 AsyncTask主要使用的4个函数,onPreExecute、doInBackground、 onProgressUpdate、onPostExecute。 2、onPreExecute是在AsyncTa...

wangqiubo2010的博客 1825

自然语言处理:长文本场景下的关键词抽取实践

自然语言处理:长文本场景下的关键词抽取实践

丨汀、的博客 2077

AsyncTask的工作原理

AsyncTask的工作原理 概述 AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新UL从实现上来说,AsyncTask封装了Thread和Handler,通过AsyncTask可以更加方便地执行后台任务以及在主线程中访问UI,但是AsyncTask并不适合进行特别耗时的后台任务,对于特别耗时的任务来说,建议使用线程...

wn1137162270的博客 1229

C语言试题三之计算并输出 s=1+(1+2^(0.5))+(1+2^(0.5)+3^(0.5))+…+(1+2^(0.5)+3^(0.5)+…+n^(0.5))

1 、题目 计算并输出 s=1+(1+2^(0.5))+(1+2^(0.5)+3^(0.5))+…+(1+2^(0.5)+3^(0.5)+…+n^(0.5)) 2、部分函数说明 C 库函数 double pow(double x, double y) 返回 x 的 y 次幂。 3、源代码实现 #include <stdio.h> #include <...

码莎拉蒂 4609

小工匠聊架构-分布式场景下的并发幂等性常见的解决方案

Pre 我们来回顾下单体时代 单体时代,应用部署在一台主机上,可以使用JVM级别的锁来控制并发请求 。 随着应用规模的不断扩大,集群化或者微服务化的分布式部署越来越普及,每个应用都是一个单独的JVM应用,所以单体时代的这种处理方式已经无法满足当前架构下的业务需求了。 JVM级别的锁已经无法满足跨进程之间访问控制了,进而演化出来了分布式锁。 分布式锁 能否解决幂等性问题? 分布式锁解决什么问题? 简言之: 解决跨进程间无法共享本地资源的问题 ,解决的是分布式场景下并发访问的问题。 为什么需要确保并发.

小工匠 2万+

AsyncTask原理及不足

一 为什么需要工作者线程 Android应用的主线程(UI线程)肩负着绘制用户界面和及时响应用户操作的重任,为了避免”ANR”,就要确保主线程时刻保持较高的响应性.为了做到这一点,我们就要把耗时的任务移出主线程,那么耗时的任务交给谁来完成呢?答案就是工作者线程。Android开发中我们通常让主线程负责前台用户界面的绘制以及响应用户的操作,让工作者线程在后台执行一些比较耗时的任务。Android中的工作者线程主要有AsyncTask、IntentService、HandlerThread,它们本质上都是对线

qq_39431405的博客 639

BLDC&PMSM电机控制器硬件设计工程(八)72V 10kW电机控制器原理图工程及库文件

电机控制器基本需求:接口类型;MCU平台;通信接口;供电;信号采集;信号输出;功率;EMC或者认证需求。

小幽余生不加糖 374

AsyncTask 学习 (2)

java.lang.Object     ↳android.os.AsyncTask 概要 AsyncTask可以方便适当地使用UI线程。他允许执行后台操作并且可以直接在UI线程上发布结果,而不需要操作线程或handler。 一个异步任务(asynchronous ta

wjdarwin的专栏 728

QPrintPreviewDialog 打印预览使用实例

qt打印机预览实用demo

啊渊的专栏 3677

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

android函数传递参数,方法 - Android:如何将参数传递给AsyncTask的onPreExecute()?...

为什么,如何以及将哪些参数传递给Asynctask&lt;&gt;,请参阅此处的详细信息。 我认为这是最好的解释。谷歌的Android文档说:异步任务由3种泛型类型定义,称为Params,Progress和Result,以及4个步骤,称为onPreExecute,doInBackground,onProgressUpdate和onPostExecute。AsyncTask的泛型类型:异步任务使用的...

weixin_33796288的博客 437

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Android实战技巧:深入解析AsyncTask

[-] AsyncTask的介绍及基本使用方法AsyncTask引发的一个问题AsyncTask的内幕 与主线程交互线程任务的调度 Android23以前的版本也即SDKAPI 10和以前的版本Android 30以后也即SDKAPI 11和以后的版本 前面问题的解法AsyncTask的使用注意事项 AsyncTask的介绍及基本使用方法 关于Async

麦田守望者 451

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

零碎知识点回顾——Android多线程AsyncTask入门讲解

Android多线程之AsyncTask AsyncTask异步任务,相当于给我们提供了一个多线程编程的一个框架,其介于Thread和Handler之间,如果我们要定义一个AsyncTask,就需要定义一个类来继承AsyncTask这个抽象类,并实现其唯一的一个odInBackground抽象方法。总结起来就是3个泛型,4个步骤。   3个泛型参数: AsyncTask &lt;Params...

递归安卓 651

再次学习AsyncTask的异步加载

  Android 提供了工具类android.os.AsyncTask,它使创建异步任务变得更加简单,但4.0后AsyncTask会有些不好使.。因为AsyncTask变成单线程工作模式,即如有多个下载任务 ,只能一个个下载,一个下载失败,就会阻瑟后的任务,进而会FC.建议使用VOllyp 这个类,其本质上也是封装了AsyncTask. 先来让我们来看看Android API中 对

zhuzhong01的博客 236

AsyncTask使用须知

AsyncTask的实现原理就是封装了的线程池,详细见AsyncTask实现原理。 在1.5中初始引入的时候, AsyncTask 运行( AsyncTask.execute() )起来是顺序的,当同一时候运行多个 AsyncTask的时候,他们会依照顺序一个一个运行。前面一个运行完才会运行后面一个。这样当同一时候运行多个比較耗时的任务的时候 可能不是您期望的结果,详细...

weixin_30307267的博客 75

android 异步ui更新ui,Android异步更新UI的四种方式

大家都知道由于性能要求,android要求只能在UI线程中更新UI,要想在其他线程中更新UI,大致有4种方式,下面分别使用四种方式来更新一个TextView。1.使用Handler消息传递机制packagecom.example.runonuithreadtest;importandroid.app.Activity;importandroid.os.Bundle;importandroi...

weixin_34916178的博客 232

详解Android中AsyncTask的使用

在Android中实现异步任务机制有两种方式,Handler和AsyncTask。Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但也是有缺点的,例如代码相对臃肿,在多个任务同时执行时,不易对线程进行精确的控制。关于Handler的相关知识,前面也有所介绍,不清楚的朋友们可以参照一下。

LiuHe 39万+

Android中异步任务机制AsyncTask的理解

在Android中实现异步任务机制有两种方式,Handler和AsyncTask。 Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但也是有缺点的,例如代码相对臃肿,在多个任务同时执行时,不易对线程进行精确的控制。关于Handler的相关知识,前面也有所介绍,不清楚的朋友们可以参照一下

lplj717的博客 2237

Android开发-AsyncTask异步下载

目录 1.同步与异步 1.同步 2.异步 2. AsyncTask 2.1 AsyncTask定义 2.2 AsyncTask目的 2.3 AsyncTask执行步骤方法 2.4 注意事项 1.同步与异步 1.同步 2.异步 顾名思义,异步就是UI主线程运行的时候,异步的完成一些操作。执行一个异步的任务在后台。我们可以将耗时的操作放在异步...

云上道人的博客 859

Android 异步操作AsyncTask

异步的轻量级实现; AsynceTask简述: 1.功能类似于Handler,都是为了防止UI线程操作阻塞而衍生而来。 2.AsyncTask是Handler的一个轻量级实现,模型类似于IntentService于Service。都是为了更加方便操作。(因为一般的异步,我们都是开启一个子线程或是匿名线程,缺点就是样的实现对于线程的操作,控制是十分困难) 3.阐述下Handler

killnono 5994

Android异步之旅:探索AsyncTask

AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终的结果传递给主线程并在主线程中更新UI。两个线程池+HandlerAsyncTask是一个抽象的泛型类,它提供了ParamsProgress和Result这三个泛型参数。其中,🟨Params表示参数的类型🟨Progress表示后台任务的执行进度和类型🟨Result表示后台任务的返回结果AsyncTask类提供了四个核心方法(按照执行顺序介绍):1️⃣在主线程中执行,用于。

weixin_63357306的博客 1010
上一篇: Android异步3:AsyncTask更新UI
下一篇: 理解Activity的生命周期
Hel1C
博客等级 码龄17年 6粉丝 106原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值