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做了简单的介绍. 但是如果线程打算一遍一遍 ...
随机推荐
- pycharm汉化(3.6版本)
step 1:下载pycharm汉化包 链接:https://pan.baidu.com/s/1htgcbZY 密码:8uia step 2:将pycharm安装目录下的lib文件夹内下的resou ...
- springboot pom.xml记
本文包括: springboot 基本pom.xml配置 热部署 配置打包插件 maven pom.xml配置详解 1. springboot 基本pom.xml配置 <project xmln ...
- linux crontab 命令,最小的执行时间是一分钟,如需要在小于一分钟内重复执行
编写shell脚本实现 crontab.sh #!/bin/bash step=2 #间隔的秒数,不能大于60 for (( i = 0; i < 60; i=(i+step) )); do $ ...
- ffmpeg 推流相关指令
1.rtsp->rtsp(只解封装,不解码) ffmpeg -re -rtsp_transport tcp -i rtsp://usr:passwd@ip:port/h264/ch1/sub/a ...
- SpringBoot+Mybatis配置Pagehelper分页插件实现自动分页
SpringBoot+Mybatis配置Pagehelper分页插件实现自动分页 **SpringBoot+Mybatis使用Pagehelper分页插件自动分页,非常好用,不用在自己去计算和组装了. ...
- html/css 表格元素以及表格布局
一,html之表格 1,一个完整的html表格所包含的元素 <!--一个完整的html表格--> <!--cellpadding代表单元格内的文字和单元格边框之间的间距--> ...
- TensorFlow学习笔记1
1.daocloud 拉取 docker镜像 docker pull daocloud.io/daocloud/tensorflow:latest 镜像位置: /Users/{YourUserName ...
- HDU5810 Balls and Boxes
Balls and Boxes Time Limi ...
- vue watch高级用法
watch是vue组件最常用,最重要的功能之一,我们都知道它最基本的特性就是监听的data对象里的属性变化了,watch就会自动执行. 那它还有什么骚操作呢?下面我带大家看看,菜鸟一枚,如有错误欢迎指 ...
- Linux 常用分区方式
1 分两个区 主目录:/ 交换分区:swap 2 常用分区方式,以使用100G空间安装linux为例 引导分区: 挂载点/boot,分区格式ext4,500M以内即可 交换分区: 无挂载点,分区格式选 ...