前言
本片博客将介绍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 }
实现效果:

浙公网安备 33010602011771号