今天介绍第二种异步更新界面的方式:AsyncTask

官方文档:

   AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

   AsyncTask能够更恰当和更简单的去使用UI线程。这个类允许执行后台操作和展现结果在UI线程上,无需操纵线程和/或处理程序。AsyncTask的内部实现是一个线程池,每个后台任务会提交到线程池中的线程执行,然后使用Thread+Handler的方式调用回调函数。

   

1.AsyncTask抽象出后台线程运行的五个状态:

   分别是:1、准备运行,2、正在后台运行,3、进度更新,4、完成后台任务,5、取消任务,对于这五个阶段,AsyncTask提供了五个回调函数:

   1、准备运行:onPreExecute(),该回调函数在任务被执行之后立即由UI线程调用。这个步骤通常用来建立任务在用户接口(UI)上显示进度条

   2、正在后台运行:doInParams...),该回调函数由后台线程在onPreExecute()方法执行结束后立即调用。通常在这里执行耗时的后台计算。计算的结果必须由该函数返回,并被传递到onPostExecute()中。在该函数内也可以使用publishProgress(Progress...)来发布一个或多个进度单位(unitsof progress)。这些值将会在onProgressUpdate(Progress...)中被发布到UI线程。

   3. 进度更新:onProgressUpdate(Progress...),该函数由UI线程在publishProgress(Progress...)方法调用完后被调用。一般用于动态地显示一个进度条

   4. 完成后台任务:onPostExecute(Result),当后台计算结束后调用。后台计算的结果会被作为参数传递给这一函数。

   5、取消任务:onCancelled (),在调用AsyncTask的cancel()方法时调用


2.使用:

   AsyncTask必须使用子类。子类会覆盖至少一个方法(doInParams…)),通常将覆盖第二个(onPostExecute(结果)。< /span>

   AsyncTask的构造函数有三个模板参数:<Params, Progress, Result>

       1.Params,传递给后台任务的参数类型。

       2.Progress,后台计算执行过程中,进步单位(progress units)的类型。(就是后台程序已经执行了百分之几了。)

       3.Result, 后台执行返回的结果的类型。


  AsyncTask并不总是需要使用上面的全部3种类型。标识不使用的类型很简单,只需要使用Void类型即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import 
java.io.InputStream;
import 
java.net.HttpURLConnection;
import 
java.net.URL;
import 
android.app.Activity;
import 
android.graphics.Bitmap;
import 
android.graphics.BitmapFactory;
import 
android.os.AsyncTask;
import 
android.os.Bundle;
import 
android.view.View;
import 
android.view.View.OnClickListener;
import 
android.widget.Button;
import 
android.widget.ImageView;
import 
android.widget.ProgressBar;
import 
android.widget.Toast;
/**
 
* AsyncTask  实现异步加载图片
 
* @author ZHF
 
*
 
*/
public 
class 
MainActivity 
extends 
Activity {
                                                                                                                                        
    
public 
static  
final 
String IMG_URL=
"http://images.51cto.com/images/index/Images/Logo.gif"
;
    
Button btn_asynctask;
    
ImageView imgView;
    
ProgressBar progressBar;
                                                                                                                                        
    
@Override
    
protected 
void 
onCreate(Bundle savedInstanceState) {
        
super
.onCreate(savedInstanceState);
        
setContentView(R.layout.activity_main);
        
//加载控件
        
imgView = (ImageView) 
this
.findViewById(R.id.imageView);
        
btn_asynctask = (Button) 
this
.findViewById(R.id.btn_AsyncTask);
        
progressBar = (ProgressBar) 
this
.findViewById(R.id.progressBar);
        
//绑定监听器
        
btn_asynctask.setOnClickListener(
new 
OnClickListener() {
            
@Override
            
public 
void 
onClick(View v) {
                
GetImgTask getImgTask = 
new 
GetImgTask();
                
getImgTask.execute(IMG_URL); 
//执行该任务
            
}
        
});
    
}
                                                                                                                                        
    
/**获取网络图片任务**/
    
private 
class 
GetImgTask 
extends 
AsyncTask<String, Integer, Bitmap> {
                                                                                                                                            
        
/**在 doInParams...)之前被调用,在ui线程执行   **/
        
@Override
        
protected 
void 
onPreExecute() {
             
imgView.setImageBitmap(
null
);
             
progressBar.setProgress(
0
);    
//进度条复位
        
}
                                                                                                                                            
        
/**在后台线程中执行的任务**/
        
@Override
        
protected 
Bitmap doInString...  params) {
                                                                                                                                                
            
publishProgress(
0
); 
//会调用onProgressUpdate更新界面
                                                                                                                                                
            
InputStream inputStream = 
null
;
            
Bitmap imgBitmap = 
null
;
            
try 
{
                
URL url = 
new 
URL(IMG_URL);
                
if
(url != 
null
) {
                    
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    
connection.setConnectTimeout(
2000
);
                    
connection.setDoInput(
true
);
                    
connection.setRequestMethod(
"GET"
);
                    
int 
code = connection.getResponseCode();
                    
if
(
200 
== code) {
                        
inputStream = connection.getInputStream();
                        
imgBitmap = BitmapFactory.decodeStream(inputStream);
                    
}
                
}
            
catch 
(Exception e) {
                
e.printStackTrace();
                
return 
null
;
            
}
            
publishProgress(
100
); 
//下载完成,更新进度条为满格
            
//这里不是UI线程,故不能直接setImage(imgBitmap),
            
return 
imgBitmap;
        
}
                                                                                                                                            
        
/**在调用publishProgress之后被调用,在ui线程执行  **/
        
@Override
        
protected 
void 
onProgressUpdate(Integer... values) {
            
progressBar.setProgress(values[
0
]);  
//设置进度条的进度
        
}
        
/**在后台线程执行完成之后,调用该方法,获取数据更新界面**/
        
@Override
        
protected 
void 
onPostExecute(Bitmap result) {
            
if
(result != 
null
) {
                
Toast.makeText(MainActivity.
this
"成功获取图片"
, Toast.LENGTH_LONG).show();
                
imgView.setImageBitmap(result);
            
}
else 
{
                
Toast.makeText(MainActivity.
this
"获取图片失败"
, Toast.LENGTH_LONG).show();
            
}
        
}
        
/**取消任务,在ui线程执行 **/
        
@Override
        
protected 
void 
onCancelled() {
            
progressBar.setProgress(
0
);
//进度条复位
            
super
.onCancelled();
        
}
    
}
}

分析:

   1.点击按钮之后,创建一个任务,参数值为url(所以第一个参数为String)

   2.UI线程执行onPreExecute(),把ImageView的图片清空,progrssbar的进度清零。

   3.后台线程执行doInBackground(),不可以在doInBackground()操作ui,调用publishProgress(0)更新进度,此时会调用onProgressUpdate(Integer...progress)更新进度条(进度用整形表示,因此AsyncTask的第二个模板参数是Integer)。函数最后返回result(例子中是返回Bitmap类型,因此AsyncTask的第三个模板参数是Bitmap)。

   4.当后台任务执行完成后,调用onPostExecute(Result),传入的参数是doInBackground()中返回的对象。


参考博客:http://blog.csdn.net/mylzc/article/details/6772129

  源码下载请看附件