Android--多线程之AsyncTask
前言
本片博客将介绍AsyncTask的使用,之前有介绍过线程和进程。而在AsyncTask中,运行在用户界面中,执行异步操作,并且把执行结果发布在UI线程上,且也不需要处理线程和Handler。在本篇博客里,将会讲解到AsyncTask的基本介绍,以及如何使用,最后会以一个简单的Demo讲解AsyncTask的使用。
AsyncTask
AsyncTask,异步任务,可以简单进行异步操作,并把执行结果发布到UI主线程。AsyncTask是一个抽象类,它的内部其实也是结合了Thread和Handler来实现异步线程操作,但是它形成了一个通用线程框架,更清晰简单。AsyncTask应该被用于比较简短的操作(最多几秒钟)。如果需要保持长时间运行的线程,可以使用ThreadPooExecutor或者FutureTask,关于这两个类的内容,以后再介绍,本片博客主要介绍AsyncTask。
AsyncTask被定义为一个操作,运行在一个后台线程中,其结果被发布在UI线程上。它的异步工作的参数与返回值被泛型的三个参数指定:Params、Progress、Result。AsyncTask将经历4个步骤:onPreExecute、doInBackground、onProgressUpdate、onPostExecute。下面详细讲解这三个参数与四个步骤:
三个泛型参数:
- Params:被发送到执行任务的参数类型。
- Progress:进度的类型,发送后台的计算进度到UI线程类型。
- Result:异步任务的返回结果类型。
一个异步任务将经历四个阶段:
- onPreExecute():执行在UI线程上调用执行任务之前,一般用于设置任务。
- doInBackground(Params...):主要是用来执行异步任务的耗时操作,可以在这个方法中通过publishProgress()方法发布进度信息,并在执行完成之后,返回执行结果。
- onProgreddUpdate(Progress...):在UI线程上接受doInBackground()传递过来的进度信息,并在UI线程上展示进度信息,它执行的时机是不确定的。
- onPostExecute(Result):在UI线程上操作doInBackground()执行的返回值。
上面介绍的四个步骤的示意图:
AsyncTask取消任务
在程序的任何位置,都可以通过cancel(boolean)方法进行取消任务,当取消任务之后,会改变isCancelled()的返回值,使其返回true。之后会调用onCancelled(Object)方法,替代onPostExecute()得到doInBackground()的返回结果。在运行中,可以经常通过isCancelled()方法查看任务是否被取消。
AsyncTask的使用规则
使用AsyncTask必须遵循以下规则:
- AsyncTask必须声明在UI线程上。
- AsyncTask必须在UI线程上实例化。
- 必须通过execute()方法执行任务。
- 不可以直接调用onPreExecute()、onPostExecute(Resut)、doInBackground(Params...)、onProgressUpdate(Progress...)方法。
- 可以设置任务只执行一次,如果企图再次执行会报错。
示例
一个简单的示例,通过AsyncTask下载一个网络上的图片,下载的时候展示一个等待框,并显示在一个ImageView中。
实现代码:
package com.bgxt.datatimepickerdemo; import org.apache.http.HttpEntity;
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 org.apache.http.util.EntityUtils; import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView; public class AsyncTaskActivity1 extends Activity {
private Button btnDown;
private ImageView ivImage;
private static String image_path = "http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg";
private ProgressDialog dialog; @Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.asynctask_activity); btnDown = (Button) findViewById(R.id.btnDown);
ivImage = (ImageView) findViewById(R.id.ivSinaImage); // 声明一个等待框以提示用户等待
dialog=new ProgressDialog(this);
dialog.setTitle("提示信息");
dialog.setMessage("正在下载,请稍后..."); btnDown.setOnClickListener(new View.OnClickListener() { @Override
public void onClick(View v) {
// 执行一个异步任务,并把图片地址以参数的形式传递进去
new MyTask().execute(image_path);
}
});
} // 以String类型的参数,Void表示没有进度信息,Bitmap表示异步任务返回一个位图
public class MyTask extends AsyncTask<String, Void, Bitmap> {
// 表示任务执行之前的操作
@Override
protected void onPreExecute() {
super.onPreExecute();
//显示等待框
dialog.show();
} //主要是完成耗时操作
@Override
protected Bitmap doInBackground(String... params) {
HttpClient httpClient=new DefaultHttpClient();
HttpGet httpGet=new HttpGet(params[0]);
Bitmap bitmap=null;
try {
//从网络上下载图片
HttpResponse httpResponse =httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode()==200){
HttpEntity httpEntity = httpResponse.getEntity();
byte[] data=EntityUtils.toByteArray(httpEntity);
bitmap=BitmapFactory.decodeByteArray(data, 0, data.length);
}
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
} //完成更新UI操作
@Override
protected void onPostExecute(Bitmap result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
//设置ImageView的显示图片
ivImage.setImageBitmap(result);
// 销毁等待框
dialog.dismiss();
} }
}
效果展示:
上面的Demo并没有用到进度的信息,下面再提供一个完整的AsyncTask的Demo,同样是下载一个图片,并且展示到一个ImageView中,但是这里在下载的过程中增加一个进度条对话框,用于展示下载的进度。
实现代码:
package com.bgxt.datatimepickerdemo; import java.io.ByteArrayOutputStream;
import java.io.InputStream; 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.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView; public class AsyncTaskActivity2 extends Activity {
private Button btnDown;
private ImageView ivImage;
private static String image_path = "http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg";
private ProgressDialog dialog; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.asynctask_activity);
btnDown = (Button) findViewById(R.id.btnDown);
ivImage = (ImageView) findViewById(R.id.ivSinaImage); dialog = new ProgressDialog(this);
dialog.setTitle("提示");
dialog.setMessage("正在下载,请稍后...");
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setCancelable(false); btnDown.setOnClickListener(new View.OnClickListener() { @Override
public void onClick(View v) {
// 执行异步任务
new MyTask().execute(image_path);
}
});
} public class MyTask extends AsyncTask<String, Integer, Bitmap> {
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog.show();
} @Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// 设置进度对话框的进度值
dialog.setProgress(values[0]);
} @Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
dialog.dismiss();
ivImage.setImageBitmap(result);
} @Override
protected Bitmap doInBackground(String... params) {
Bitmap bitmap = null;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
InputStream inputStream = null;
try {
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(params[0]);
HttpResponse httpResponse = httpClient.execute(httpGet);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
inputStream = httpResponse.getEntity().getContent();
long file_length = httpResponse.getEntity()
.getContentLength();
int len = 0;
byte[] data = new byte[1024];
int total_length = 0;
// 以字节的方式读取图片数据
while ((len = inputStream.read(data)) != -1) {
total_length += len;
// 计算进度
int values = (int) ((total_length / (float) file_length) * 100);
// 发布进度信息
publishProgress(values);
outputStream.write(data, 0, len);
}
byte[] result=outputStream.toByteArray();
bitmap=BitmapFactory.decodeByteArray(result, 0, result.length);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (Exception e2) {
}
}
return bitmap;
}
}
}
实现效果:

Android--多线程之AsyncTask的更多相关文章
- Android 多线程之IntentService 完全详解
关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...
- Android 多线程之HandlerThread 完全详解
关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...
- Android线程之AsyncTask
在之前的博客中为大家分享过关于Android多线程处理,想必大家对于Android为什么要使用多线程已经有了清晰的认识,我就在简单唠两句,Android规定UI界面的更新必须在在主线程进行,对于访问网 ...
- Android多线程编程之AsyncTask
进程?线程? 进程是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态的概念.每个进程都有自己的地址空间(进程空间).进程空间的大小与处理机位数有关.进程至少有5种基本状态:初始态,执行态 ...
- Android——多线程之Handler
Why? 因为在Android系统中UI操作并不是线程安全的,如果多个线程并发的去操作同一个组件,可能导致线程安全问题.为了解决这一个问题, android制定了一条规则:只允许UI线程来修改UI组件 ...
- Android-——多线程之Handler(转)
Android--多线程之Handler 原文地址:http://www.cnblogs.com/shirley-1019/p/3557800.html 前言 Android的消息传递机制是另外一种形 ...
- Android线程管理之AsyncTask异步任务
前言: 前面几篇文章主要学习了线程以及线程池的创建与使用,今天来学习一下AsyncTask异步任务,学习下AsyncTask到底解决了什么问题?然而它有什么弊端?正所谓知己知彼百战百胜嘛! 线程管理相 ...
- iOS多线程之8.NSOPeration的其他用法
本文主要对NSOPeration的一些重点属性和方法做出介绍,以便大家可以更好的使用NSOPeration. 1.添加依赖 - (void)addDependency:(NSOperation * ...
- python 线程之 threading(四)
python 线程之 threading(三) http://www.cnblogs.com/someoneHan/p/6213100.html中对Event做了简单的介绍. 但是如果线程打算一遍一遍 ...
随机推荐
- 本地iis新建站点步骤
例如:1.在C:\Windows\System32\drivers\etc\hosts下添加地址 2.在下面IIS加上名称与webUI的地址
- 离线eclipse添加web工程
下载了eclipse,先写的后台程序,后来写前台程序的时候发现没有 新建->web dynamic project,如下方式添加: 帮助->安装新软件,在work with中选择版本对应的 ...
- mongooDb链接javaapi
mongodb链接有多种:所以不同链接下的api也不太一样. 1.api比较全面 public void query2(){ String mondburl = Config.getInstance( ...
- go基本使用方法
一,变量 var:声明变: var 变量名 数据类型 :同时还需要指定数据的类型 var 变量名 = 值 : 声明变量,根据变量值判断变量类型 := :省略var,直接可以(变量名:= 值), ...
- 如何在Ubuntu上安装LAMP服务器系统?
在Ubuntu上安装LAMP Ubuntu的开发人员让人们很容易安装和配置LAMP软件包,只要借助一个终端命令.所以,打开终端窗口,让我们开始入手吧. sudo apt-get install lam ...
- 用idea部署maven-web项目
项目部署时,需要加一步: 我们需要添加一个archetypeCatalog=internal.这个参数的意义是让这个maven项目的骨架不要到远程下载而是本地获取.如果你没加这个参数,那么项目创建可能 ...
- ext__给grid Panel设置绑定事件
使用面板来展示详情信息 1.创建一个面板 (双击添加) 2.给该面板设置itemid的值为:detailPanel 3.给面板设置模板 4.添加下面的内容 id:{id}</br> nam ...
- 安装vue-cli脚手架构建工具
vue安装 1.vue安装: $ cnpm install vue 2.安装vue-cli脚手架构建工具: # 全局安装 vue-cli $ cnpm install --global vue-cli ...
- Reader和Writer
- 常用类:Object
2017-08-08 Object :作为所有类的根类,(超类,父类) 常用的方法: public int hasCode(){//返回该对象的哈希码值(地址)}:判断对象是否在同一内存地址上 pub ...