Android AsyncTask 初探

因为在开发Android应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。在单线程模型中始终要记住两条法则: 

1. 不要阻塞UI线程 
2. 确保只在UI线程中访问Android UI工具包 

(当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程。)

android提供了几种在其他线程中访问UI线程的方法。 
Activity.runOnUiThread( Runnable ) 
View.post( Runnable ) 
View.postDelayed( Runnable, long ) 
Hanlder

(在之前的《线程与消息处理》中我们学习了线程和Handler消息处理机制,如果有计算量比较大的任务,可以创建一个新线程执行计算工作,但是子线程无法更新UI界面,所以通过Handler消息处理机制与UI线程通信,更新UI界面。)

但是有一个问题需要注意,创建的子线程太多时,会影响系统性能。而且,Hanlder这种方式对于整个过程的控制比较精细,但也是有缺点的,例如代码相对臃肿,在多个任务同时执行时,不易对线程进行精确的控制。针对这个问题,Android为我们提供了代替使用Thread和Handler的方案,这就是AsyncTask。它使创建需要与用户界面交互的长时间运行的任务变得更简单。

下面我们来直接认识AsyncTask :

先来看看AsyncTask的定义:

public abstract class AsyncTask<Params, Progress, Result> 三种泛型类型分别代表“启动任务执行的输入参数”、“后台任务执行的进度”、“后台计算结果的类型”。在特定场合下,并不是所有类型都被使用,如果没有被使用,可以用java.lang.Void类型代替。

一个异步任务的执行一般包括以下几个步骤:

1.execute(Params... params),执行一个异步任务,需要我们在代码中调用此方法,触发异步任务的执行。

2.onPreExecute(),在execute(Params... params)被调用后立即执行,一般用来在执行后台任务前对UI做一些标记。

3.doInBackground(Params... params),在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。

4.onProgressUpdate(Progress... values),在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。

5.onPostExecute(Result result),当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。

使用AsyncTask类,遵守的准则:

  1. Task的实例必须在UI thread中创建;
  2. Execute()方法必须在UI thread中调用;
  3. 不要手动的调用onPfreexecute(),onPostExecute(result)Doinbackground(params…),onProgressupdate(progress…)这几个方法;
  4. 该task只能被执行一次,否则多次调用时将会出现异常;
  5. 不能在doInBackground(Params... params)中更改UI组件的信息。

 

通过看源码,发现AsyncTask实际上就是一个线程池,而网上的说法是AsyncTask比handler要轻量级,显然上不准确的,只能这样说,AsyncTask在代码上比handler要轻量级别,而实际上要比handler更耗资源,因为AsyncTask底层是一个线程池!而Handler仅仅就是发送了一个消息队列,连线程都没有开。
但是,如果异步任务的数据特别庞大,AsyncTask这种线程池结构的优势就体现出来了。

下面我们用一个简单的例子来体验一下:

布局文件:

 

Android AsyncTask 初探
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="fill_parent"
 4     android:layout_height="fill_parent"
 5     android:orientation="vertical" >
 6     <TextView  
 7         android:layout_width="fill_parent"  
 8         android:layout_height="200dp"  
 9         android:id="@+id/textView"  
10         android:textSize="20dp"  
11         android:gravity="center" />
12     <Button  
13         android:layout_width="wrap_content"  
14         android:layout_height="wrap_content"  
15         android:id="@+id/button"  
16         android:layout_gravity="center"  
17         android:textSize="20dp"  
18         android:text="启动AsyncTask"  />
19     <ProgressBar   
20         android:id="@+id/progress_bar"   
21         android:layout_width="match_parent"   
22         android:layout_height="wrap_content"   
23         android:progress="0"  
24         android:max="9"  
25         style="@android:style/Widget.ProgressBar.Horizontal"/> 
26 
27 </LinearLayout>
View Code

 

在MainActivity中实现代码:

Android AsyncTask 初探
 1 public class MainActivity extends Activity {
 2     private static final String TAG = "topcsa";
 3     TextView textView; 
 4     Button button;
 5     private ProgressBar progressBar;
 6     @Override
 7     protected void onCreate(Bundle savedInstanceState) {
 8         super.onCreate(savedInstanceState);
 9         setContentView(R.layout.main);
10          textView = (TextView)findViewById(R.id.textView);  
11             button = (Button)findViewById(R.id.button);  
12             progressBar = (ProgressBar) findViewById(R.id.progress_bar);
13             button.setOnClickListener(new View.OnClickListener(){  
14            
15                 @Override  
16                 public void onClick(View v) {  
17                     // TODO Auto-generated method stub  
18                     MyAsyncTask asyncTask = new MyAsyncTask();  
19                     asyncTask.execute(1000);  
20                 }  
21             }); 
22         
23     }
24     
25     
26     class MyAsyncTask extends AsyncTask<Integer, Integer, String>  
27        {  
28         @Override  
29             protected void onPreExecute() {  
30                 // TODO Auto-generated method stub  
31                 super.onPreExecute();  
32                 Log.d(TAG, "onPreExecute");  
33             }
34 
35         @Override
36         protected String doInBackground(Integer... params) {
37             // TODO Auto-generated method stub
38             Log.d(TAG, "doInBackground");  
39             for(int i = 0; i < 10; i++)  
40             {  
41                 publishProgress(i);  
42                 try {  
43                     Thread.sleep(params[0]);  
44                 }catch(InterruptedException e) {  
45                     // TODO Auto-generated catch block  
46                     e.printStackTrace();  
47                 }  
48             }  
49             Log.d(TAG, "Background work over");  
50             return "Background work over."; 
51         }  
52         @Override  
53         protected void onProgressUpdate(Integer... values) {  
54             // TODO Auto-generated method stub  
55             super.onProgressUpdate(values);  
56             Log.d(TAG, "onProgressUpdate"); 
57             progressBar.setProgress(values[0]);
58             textView.setText(Integer.toString(values[0]));  
59         }
60         
61         @Override  
62         protected void onPostExecute(String result) {  
63             // TODO Auto-generated method stub  
64             super.onPostExecute(result);  
65             Log.d(TAG, "onPostExecute, result = " + result);  
66         }
67             
68        } 
View Code

运行程序时,做好与日志输出信息对照查看,有助于更好地理解AsyncTask的运作。

 

当然,AsyncTask也不是完全的完美。下面加个有关AsyncTask不足的文章:

http://www.oschina.net/question/54100_27825

 

Android AsyncTask 初探,布布扣,bubuko.com

Android AsyncTask 初探

上一篇:mono for android学习过程系列教程(6)


下一篇:Android 用Activity的onTouchEvent来监听滑动手势