Android多线程--AsyncTask
常见的多线程方法有:
- 继承Thread类
- 实现Runnable接口
- Handler
- AsyncTask
- HandlerThread
1.定义
- 一个Android已经封装好的轻量级异步类
- 属于抽象类,即使用时需要实现的子类
public abstract class AsyncTask<Params, Progress, Result> {
...
}
2.作用
- 实现多线程
在工作线程中执行任务,如耗时任务。 - 异步通信,消息传递
实现工作线程和主线程之间的通信,即将工作线程的执行结果传递给主线程,从而在主线程中执行相关的UI操作,从而保证线程安全。
3. 优点
- 方便实现异步通信:
不需要使用“任务线程(如继承Thread类)+Handler“的复杂组合 - 节省资源:
采用线程池的缓存线程+复用线程,避免了频繁创建&销毁线程所带来的系统资源开销。
4.类和方法
4.1类的定义
AsyncTask类术语抽象类,即使用时需要实现子类
public abstract class AsyncTask<Params, Progress, Result> {
...
}
// 类中参数为3种泛型类型
// 整体作用:控制AsyncTask子类执行线程任务时各个阶段的返回类型
// 具体说明:
// a. Params:开始异步任务执行时传入的参数类型,对应excute()中
// b. Progress:异步任务执行过程中,返回下载进度值的类型
// c. Result:异步任务执行完成后,返回的结果类型,与doInBackground()的返回值类型保持一致
// 注:
// a. 使用时并不是所有类型都被使用
// b. 若无被使用,可用java.lang.Void类型代替
// c. 若有不同业务,需额外再写1个AsyncTask的子类
}
4.2核心方法
核心方法如下:

方法的执行顺序:

5.使用步骤
- 创建AsyncTask子类并根据需要实现核心方法
- 创建AsyncTask子类的实例对象
- 手动调用execute()从而执行异步线程任务
/**
* 步骤1:创建AsyncTask子类
* 注:
* a. 继承AsyncTask类
* b. 为3个泛型参数指定类型;若不使用,可用java.lang.Void类型代替
* c. 根据需求,在AsyncTask子类内实现核心方法
*/
private class MyTask extends AsyncTask<Params, Progress, Result> {
....
// 方法1:onPreExecute()
// 作用:执行 线程任务前的操作
// 注:根据需求复写
@Override
protected void onPreExecute() {
...
}
// 方法2:doInBackground()
// 作用:接收输入参数、执行任务中的耗时操作、返回 线程任务执行的结果
// 注:必须复写,从而自定义线程任务
@Override
protected String doInBackground(String... params) {
...// 自定义的线程任务
// 可调用publishProgress()显示进度, 之后将执行onProgressUpdate()
publishProgress(count);
}
// 方法3:onProgressUpdate()
// 作用:在主线程 显示线程任务执行的进度
// 注:根据需求复写
@Override
protected void onProgressUpdate(Integer... progresses) {
...
}
// 方法4:onPostExecute()
// 作用:接收线程任务执行结果、将执行结果显示到UI组件
// 注:必须复写,从而自定义UI操作
@Override
protected void onPostExecute(String result) {
...// UI操作
}
// 方法5:onCancelled()
// 作用:将异步任务设置为:取消状态
@Override
protected void onCancelled() {
...
}
}
/**
* 步骤2:创建AsyncTask子类的实例对象(即 任务实例)
* 注:AsyncTask子类的实例必须在UI线程中创建
*/
MyTask mTask = new MyTask();
/**
* 步骤3:手动调用execute(Params... params) 从而执行异步线程任务
* 注:
* a. 必须在UI线程中调用
* b. 同一个AsyncTask实例对象只能执行1次,若执行第2次将会抛出异常
* c. 执行任务中,系统会自动调用AsyncTask的一系列方法:onPreExecute() 、doInBackground()、onProgressUpdate() 、onPostExecute()
* d. 不能手动调用上述方法
*/
mTask.execute();
6.具体实例
public class MainActivity extends AppCompatActivity {
// 线程变量
MyTask mTask;
// 主布局中的UI组件
Button button,cancel; // 加载、取消按钮
TextView text; // 更新的UI组件
ProgressBar progressBar; // 进度条
/**
* 步骤1:创建AsyncTask子类
* 注:
* a. 继承AsyncTask类
* b. 为3个泛型参数指定类型;若不使用,可用java.lang.Void类型代替
* 此处指定为:输入参数 = String类型、执行进度 = Integer类型、执行结果 = String类型
* c. 根据需求,在AsyncTask子类内实现核心方法
*/
private class MyTask extends AsyncTask<String, Integer, String> {
// 方法1:onPreExecute()
// 作用:执行 线程任务前的操作
@Override
protected void onPreExecute() {
text.setText("加载中");
// 执行前显示提示
}
// 方法2:doInBackground()
// 作用:接收输入参数、执行任务中的耗时操作、返回 线程任务执行的结果
// 此处通过计算从而模拟“加载进度”的情况
@Override
protected String doInBackground(String... params) {
try {
int count = 0;
int length = 1;
while (count<99) {
count += length;
// 可调用publishProgress()显示进度, 之后将执行onProgressUpdate()
publishProgress(count);
// 模拟耗时任务
Thread.sleep(50);
}
}catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
// 方法3:onProgressUpdate()
// 作用:在主线程 显示线程任务执行的进度
@Override
protected void onProgressUpdate(Integer... progresses) {
progressBar.setProgress(progresses[0]);
text.setText("loading..." + progresses[0] + "%");
}
// 方法4:onPostExecute()
// 作用:接收线程任务执行结果、将执行结果显示到UI组件
@Override
protected void onPostExecute(String result) {
// 执行完毕后,则更新UI
text.setText("加载完毕");
}
// 方法5:onCancelled()
// 作用:将异步任务设置为:取消状态
@Override
protected void onCancelled() {
text.setText("已取消");
progressBar.setProgress(0);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 绑定UI组件
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
cancel = (Button) findViewById(R.id.cancel);
text = (TextView) findViewById(R.id.text);
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
/**
* 步骤2:创建AsyncTask子类的实例对象(即 任务实例)
* 注:AsyncTask子类的实例必须在UI线程中创建
*/
mTask = new MyTask();
// 加载按钮按按下时,则启动AsyncTask
// 任务完成后更新TextView的文本
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/**
* 步骤3:手动调用execute(Params... params) 从而执行异步线程任务
* 注:
* a. 必须在UI线程中调用
* b. 同一个AsyncTask实例对象只能执行1次,若执行第2次将会抛出异常
* c. 执行任务中,系统会自动调用AsyncTask的一系列方法:onPreExecute() 、doInBackground()、onProgressUpdate() 、onPostExecute()
* d. 不能手动调用上述方法
*/
mTask.execute();
}
});
cancel = (Button) findViewById(R.id.cancel);
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 取消一个正在执行的任务,onCancelled方法将会被调用
mTask.cancel(true);
}
});
}
}

Android多线程--AsyncTask的更多相关文章
- android多线程-AsyncTask之工作原理深入解析(下)
关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...
- android多线程-AsyncTask之工作原理深入解析(上)
关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...
- Android 多线程----AsyncTask异步任务详解
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3 ...
- android 多线程 AsyncTask 下载图片
AsyncTask 下载图片 package com.test.network; import android.graphics.Bitmap; import android.graphics.Bit ...
- Android 多线程-----AsyncTask详解
您可以通过点击 右下角 的按钮 来对文章内容作出评价, 也可以通过左下方的 关注按钮 来关注我的博客的最新动态. 如果文章内容对您有帮助, 不要忘记点击右下角的 推荐按钮 来支持一下哦 如果您对文章内 ...
- Android多线程----异步消息处理机制之Handler详解
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- Android多线程编程之AsyncTask
进程?线程? 进程是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态的概念.每个进程都有自己的地址空间(进程空间).进程空间的大小与处理机位数有关.进程至少有5种基本状态:初始态,执行态 ...
- Android多线程分析之五:使用AsyncTask异步下载图像
Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<An ...
- Android多线程任务优化1:探讨AsyncTask的缺陷
AsyncTask还有别的缺陷,在生成listview的时候,如果adapter里面的count动态改变的话,不能使用AsyncTask,只能使用Thread+Handler,否则会出现如下错误 j ...
随机推荐
- Python实用笔记 (24)面向对象高级编程——使用@property
这显然不合逻辑.为了限制score的范围,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数: clas ...
- 【WPF】DataGrid多表头的样式设计
需求 在使用WPF开发时,使用DataGrid列表显示数据时,有些字段可以进行分组显示,用于更好的表达它们之间存在的某种关系,因此就考虑到要对DataGrid的表头进行扩展,可以显示多行表头,让这些有 ...
- Unicode 环境下的字符串的操作
1.CString转int int i _ttoi( str ); 2.保存中文和读取中文: CSdtioFile在Unicode环境下默认是不支持中文的,若需要存储和读取中文需要设置代码页: #in ...
- 简单的Linq查询语句
下面我来我大家介绍几种简单的查询方式. 1.简单语法 这个LINQ语句的第一个关键字是from,from后面加的是范围变量,范围变量后加in,后加上事先实例化的模型,然后点出数据的来源. List是列 ...
- python之浅谈数据类型
什么是数据类型 数据类型指的就是变量值的不同类型,姓名可能是一种数据类型.年龄可能是一种数据类型.爱好可能又是另一种数据类型,至于是什么数据类型我们将在下一章详细说明. 如何对数据分类 变量的是用 ...
- 读取和写入blob类型数据
读写oracle blob类型 http://zyw090111.iteye.com/blog/607869 http://blog.csdn.net/jeryjeryjery/article/de ...
- 你真的了解CSS继承吗?看完必跪
也许你瞧不起以前的 css ,但是你不该再轻视眼下的 css .近年来 css 的变量系统已逐步得到各大浏览器厂商支持,自定义选择器等强势袭来,嵌套系统/模块系统也在路上…为了更好的掌握 css 这门 ...
- MySQL授权--WITH GRANT OPTION
今天在学习MySQL的时候,看到一句描述 WITH GRANT OPTION should be left out if the user need not be able to grant othe ...
- 转载---最简单的JavaScript模板引擎
转载自:http://www.cnblogs.com/dolphinX/p/3489269.html,http://blog.jobbole.com/56689/
- day16 三层装饰器和迭代器
一. 经典的两层装饰器,也是标准装饰器 案例 import time def outter1(func): def wrapper(*args, **kwargs): start = time.tim ...