前言

  本片博客将介绍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的更多相关文章

  1. Android 多线程之IntentService 完全详解

    关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...

  2. Android 多线程之HandlerThread 完全详解

    关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...

  3. Android线程之AsyncTask

    在之前的博客中为大家分享过关于Android多线程处理,想必大家对于Android为什么要使用多线程已经有了清晰的认识,我就在简单唠两句,Android规定UI界面的更新必须在在主线程进行,对于访问网 ...

  4. Android多线程编程之AsyncTask

    进程?线程? 进程是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态的概念.每个进程都有自己的地址空间(进程空间).进程空间的大小与处理机位数有关.进程至少有5种基本状态:初始态,执行态 ...

  5. Android——多线程之Handler

    Why? 因为在Android系统中UI操作并不是线程安全的,如果多个线程并发的去操作同一个组件,可能导致线程安全问题.为了解决这一个问题, android制定了一条规则:只允许UI线程来修改UI组件 ...

  6. Android-——多线程之Handler(转)

    Android--多线程之Handler 原文地址:http://www.cnblogs.com/shirley-1019/p/3557800.html 前言 Android的消息传递机制是另外一种形 ...

  7. Android线程管理之AsyncTask异步任务

    前言: 前面几篇文章主要学习了线程以及线程池的创建与使用,今天来学习一下AsyncTask异步任务,学习下AsyncTask到底解决了什么问题?然而它有什么弊端?正所谓知己知彼百战百胜嘛! 线程管理相 ...

  8. iOS多线程之8.NSOPeration的其他用法

      本文主要对NSOPeration的一些重点属性和方法做出介绍,以便大家可以更好的使用NSOPeration. 1.添加依赖 - (void)addDependency:(NSOperation * ...

  9. python 线程之 threading(四)

    python 线程之 threading(三) http://www.cnblogs.com/someoneHan/p/6213100.html中对Event做了简单的介绍. 但是如果线程打算一遍一遍 ...

随机推荐

  1. PL/SQL Developer 破解方法~

    1.有注册码的方式:亲自测试,立马见效 LicenseNumber : 999 productCode : 46jvnzf74ysf3mqm4hx4tvhcamh8gpe3v5 SeriesNumbe ...

  2. 磨人的Fragment的转换

    磨人的Fragment的转换 本次任务是 程序运行之后将第一个Fragment加载出来 然后点击"SHOW NEXT PAGE"切换到第二个Fragment 当再次点击按钮时下方出 ...

  3. 招聘ETL开发工程师

    上班地点徐汇 本科以上学历 3年以上ETL开发经验熟悉Oracle数据库,精通PL  SQL开发与优化,熟悉Vertica或者GreenPlum库优先 熟悉数据库性能优化,有海量数据处理经验优先 自荐 ...

  4. Toggle组件切换开关,控制开关图片显示与隐藏

    UGUI_Image 组件简单笔记 Rect Transform:用于控制 UI 物体的基本属性 Image 基本使用 1.Image 组件是用于显示图片资源的.使用方式有两种:1.显示纯粹的颜色:2 ...

  5. JAVA 8 主要新特性 ----------------(七)新时间日期 API -----LocalDate

    一.改版原因 1.老板的Date和Calander存在问题,日期操作名称混乱,有的在text下,有的在util下,包名混乱         2.Simple包混乱,致命错误线程不安全.        ...

  6. shell遍历文件夹

    遍历目录下的所有文件 假如有一个文件夹路径为dir,遍历文件 for file in /path/dir/* do if test -f $file then echo $file arrary=($ ...

  7. U-Boot bootargs简析

    Linux内核启动时需要一些配置信息,如根文件系统的类型.flash分区情况.串口终端的编号.内存的使用情况等等,而由于U-Boot和Linux Kernel的镜像是独立的两个文件,所以只能两者约定好 ...

  8. 无知小子踏入python web大门

    学习python flask的第一天,费劲我小白的脑子,总算完成了环境配置 详情如下,其他小白误走弯路,希望和我一样爱好python的人坚信:python或许是最好的语言! 那么,开始喽,有不对的地方 ...

  9. Debian 8下手工安装 Eclipse CDT neon.2

    从 http://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/neon2 下载 eclipse-cpp-neon-2-li ...

  10. 人工智能之一般合一算法Java实现之

    import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Scanner ...