前言

  本片博客将介绍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中。

  实现代码:

  1. package com.bgxt.datatimepickerdemo;
  2.  
  3. import org.apache.http.HttpEntity;
  4. import org.apache.http.HttpResponse;
  5. import org.apache.http.client.HttpClient;
  6. import org.apache.http.client.methods.HttpGet;
  7. import org.apache.http.impl.client.DefaultHttpClient;
  8. import org.apache.http.util.EntityUtils;
  9.  
  10. import android.app.Activity;
  11. import android.app.ProgressDialog;
  12. import android.graphics.Bitmap;
  13. import android.graphics.BitmapFactory;
  14. import android.os.AsyncTask;
  15. import android.os.Bundle;
  16. import android.view.View;
  17. import android.widget.Button;
  18. import android.widget.ImageView;
  19.  
  20. public class AsyncTaskActivity1 extends Activity {
  21. private Button btnDown;
  22. private ImageView ivImage;
  23. private static String image_path = "http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg";
  24. private ProgressDialog dialog;
  25.  
  26. @Override
  27. protected void onCreate(Bundle savedInstanceState) {
  28. // TODO Auto-generated method stub
  29. super.onCreate(savedInstanceState);
  30. setContentView(R.layout.asynctask_activity);
  31.  
  32. btnDown = (Button) findViewById(R.id.btnDown);
  33. ivImage = (ImageView) findViewById(R.id.ivSinaImage);
  34.  
  35. // 声明一个等待框以提示用户等待
  36. dialog=new ProgressDialog(this);
  37. dialog.setTitle("提示信息");
  38. dialog.setMessage("正在下载,请稍后...");
  39.  
  40. btnDown.setOnClickListener(new View.OnClickListener() {
  41.  
  42. @Override
  43. public void onClick(View v) {
  44. // 执行一个异步任务,并把图片地址以参数的形式传递进去
  45. new MyTask().execute(image_path);
  46. }
  47. });
  48. }
  49.  
  50. // 以String类型的参数,Void表示没有进度信息,Bitmap表示异步任务返回一个位图
  51. public class MyTask extends AsyncTask<String, Void, Bitmap> {
  52. // 表示任务执行之前的操作
  53. @Override
  54. protected void onPreExecute() {
  55. super.onPreExecute();
  56. //显示等待框
  57. dialog.show();
  58. }
  59.  
  60. //主要是完成耗时操作
  61. @Override
  62. protected Bitmap doInBackground(String... params) {
  63. HttpClient httpClient=new DefaultHttpClient();
  64. HttpGet httpGet=new HttpGet(params[0]);
  65. Bitmap bitmap=null;
  66. try {
  67. //从网络上下载图片
  68. HttpResponse httpResponse =httpClient.execute(httpGet);
  69. if(httpResponse.getStatusLine().getStatusCode()==200){
  70. HttpEntity httpEntity = httpResponse.getEntity();
  71. byte[] data=EntityUtils.toByteArray(httpEntity);
  72. bitmap=BitmapFactory.decodeByteArray(data, 0, data.length);
  73. }
  74. } catch (Exception e) {
  75. e.printStackTrace();
  76. }
  77. return bitmap;
  78. }
  79.  
  80. //完成更新UI操作
  81. @Override
  82. protected void onPostExecute(Bitmap result) {
  83. // TODO Auto-generated method stub
  84. super.onPostExecute(result);
  85. //设置ImageView的显示图片
  86. ivImage.setImageBitmap(result);
  87. // 销毁等待框
  88. dialog.dismiss();
  89. }
  90.  
  91. }
  92. }

  效果展示:

  

  上面的Demo并没有用到进度的信息,下面再提供一个完整的AsyncTask的Demo,同样是下载一个图片,并且展示到一个ImageView中,但是这里在下载的过程中增加一个进度条对话框,用于展示下载的进度。

  实现代码:

  1. package com.bgxt.datatimepickerdemo;
  2.  
  3. import java.io.ByteArrayOutputStream;
  4. import java.io.InputStream;
  5.  
  6. import org.apache.http.HttpResponse;
  7. import org.apache.http.client.HttpClient;
  8. import org.apache.http.client.methods.HttpGet;
  9. import org.apache.http.impl.client.DefaultHttpClient;
  10.  
  11. import android.app.Activity;
  12. import android.app.ProgressDialog;
  13. import android.graphics.Bitmap;
  14. import android.graphics.BitmapFactory;
  15. import android.os.AsyncTask;
  16. import android.os.Bundle;
  17. import android.view.View;
  18. import android.widget.Button;
  19. import android.widget.ImageView;
  20.  
  21. public class AsyncTaskActivity2 extends Activity {
  22. private Button btnDown;
  23. private ImageView ivImage;
  24. private static String image_path = "http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg";
  25. private ProgressDialog dialog;
  26.  
  27. @Override
  28. protected void onCreate(Bundle savedInstanceState) {
  29. super.onCreate(savedInstanceState);
  30. setContentView(R.layout.asynctask_activity);
  31. btnDown = (Button) findViewById(R.id.btnDown);
  32. ivImage = (ImageView) findViewById(R.id.ivSinaImage);
  33.  
  34. dialog = new ProgressDialog(this);
  35. dialog.setTitle("提示");
  36. dialog.setMessage("正在下载,请稍后...");
  37. dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
  38. dialog.setCancelable(false);
  39.  
  40. btnDown.setOnClickListener(new View.OnClickListener() {
  41.  
  42. @Override
  43. public void onClick(View v) {
  44. // 执行异步任务
  45. new MyTask().execute(image_path);
  46. }
  47. });
  48. }
  49.  
  50. public class MyTask extends AsyncTask<String, Integer, Bitmap> {
  51. @Override
  52. protected void onPreExecute() {
  53. super.onPreExecute();
  54. dialog.show();
  55. }
  56.  
  57. @Override
  58. protected void onProgressUpdate(Integer... values) {
  59. super.onProgressUpdate(values);
  60. // 设置进度对话框的进度值
  61. dialog.setProgress(values[0]);
  62. }
  63.  
  64. @Override
  65. protected void onPostExecute(Bitmap result) {
  66. super.onPostExecute(result);
  67. dialog.dismiss();
  68. ivImage.setImageBitmap(result);
  69. }
  70.  
  71. @Override
  72. protected Bitmap doInBackground(String... params) {
  73. Bitmap bitmap = null;
  74. ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
  75. InputStream inputStream = null;
  76. try {
  77. HttpClient httpClient = new DefaultHttpClient();
  78. HttpGet httpGet = new HttpGet(params[0]);
  79. HttpResponse httpResponse = httpClient.execute(httpGet);
  80. if (httpResponse.getStatusLine().getStatusCode() == 200) {
  81. inputStream = httpResponse.getEntity().getContent();
  82. long file_length = httpResponse.getEntity()
  83. .getContentLength();
  84. int len = 0;
  85. byte[] data = new byte[1024];
  86. int total_length = 0;
  87. // 以字节的方式读取图片数据
  88. while ((len = inputStream.read(data)) != -1) {
  89. total_length += len;
  90. // 计算进度
  91. int values = (int) ((total_length / (float) file_length) * 100);
  92. // 发布进度信息
  93. publishProgress(values);
  94. outputStream.write(data, 0, len);
  95. }
  96. byte[] result=outputStream.toByteArray();
  97. bitmap=BitmapFactory.decodeByteArray(result, 0, result.length);
  98. }
  99. } catch (Exception e) {
  100. e.printStackTrace();
  101. } finally {
  102. try {
  103. if (inputStream != null) {
  104. inputStream.close();
  105. }
  106. } catch (Exception e2) {
  107. }
  108. }
  109. return bitmap;
  110. }
  111. }
  112. }

  实现效果:

  源码下载

 

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. pycharm汉化(3.6版本)

    step 1:下载pycharm汉化包  链接:https://pan.baidu.com/s/1htgcbZY 密码:8uia step 2:将pycharm安装目录下的lib文件夹内下的resou ...

  2. springboot pom.xml记

    本文包括: springboot 基本pom.xml配置 热部署 配置打包插件 maven pom.xml配置详解 1. springboot 基本pom.xml配置 <project xmln ...

  3. linux crontab 命令,最小的执行时间是一分钟,如需要在小于一分钟内重复执行

    编写shell脚本实现 crontab.sh #!/bin/bash step=2 #间隔的秒数,不能大于60 for (( i = 0; i < 60; i=(i+step) )); do $ ...

  4. ffmpeg 推流相关指令

    1.rtsp->rtsp(只解封装,不解码) ffmpeg -re -rtsp_transport tcp -i rtsp://usr:passwd@ip:port/h264/ch1/sub/a ...

  5. SpringBoot+Mybatis配置Pagehelper分页插件实现自动分页

    SpringBoot+Mybatis配置Pagehelper分页插件实现自动分页 **SpringBoot+Mybatis使用Pagehelper分页插件自动分页,非常好用,不用在自己去计算和组装了. ...

  6. html/css 表格元素以及表格布局

    一,html之表格 1,一个完整的html表格所包含的元素 <!--一个完整的html表格--> <!--cellpadding代表单元格内的文字和单元格边框之间的间距--> ...

  7. TensorFlow学习笔记1

    1.daocloud 拉取 docker镜像 docker pull daocloud.io/daocloud/tensorflow:latest 镜像位置: /Users/{YourUserName ...

  8. HDU5810 Balls and Boxes

    Balls and Boxes                                                                            Time Limi ...

  9. vue watch高级用法

    watch是vue组件最常用,最重要的功能之一,我们都知道它最基本的特性就是监听的data对象里的属性变化了,watch就会自动执行. 那它还有什么骚操作呢?下面我带大家看看,菜鸟一枚,如有错误欢迎指 ...

  10. Linux 常用分区方式

    1 分两个区 主目录:/ 交换分区:swap 2 常用分区方式,以使用100G空间安装linux为例 引导分区: 挂载点/boot,分区格式ext4,500M以内即可 交换分区: 无挂载点,分区格式选 ...