android通过线程来解决主线程的的一些耗时操作。android的线程通过Handler,Looper,Message Queues和Message来进行线程之间的通信。在android中有两种实现线程thread的方法:一种是,扩展java.lang.Thread类 ,另一种是,实现Runnable接口。它的两个最主要的方法是: run()——包含线程运行时所执行的代码    Start()——用于启动线程。

     

1. Message
    Message消息,理解为线程间交流的信息,处理数据后台线程需要更新UI,则发送Message内含一些数据给UI线程。
 
    2. Handler
    Handler处理者,是Message的主要处理者,负责Message的发送,Message内容的执行处理。后台线程就是通过传进来的Handler对象引用来sendMessage(Message)。而使用Handler,需要implement 该类的 handleMessage(Message)方法,它是处理这些Message的操作内容,例如Update UI。通常需要子类化Handler来实现handleMessage方法。
 
    3. Message Queue
    Message Queue消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
    每个message queue都会有一个对应的Handler。Handler会向message queue通过两种方法发送消息:sendMessage或post。这两种消息都会插在message queue队尾并按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过sendMessage发送的是一个message对象,会被Handler的handleMessage()函数处理;而通过post方法发送的是一个runnable对象,则会自己执行。
 
    4. Looper
    Looper是每条线程里的Message Queue的管家。Android没有Global的Message Queue,而Android会自动替主线程(UI线程)建立Message Queue,但在子线程里并没有建立Message Queue。所以调用Looper.getMainLooper()得到的主线程的Looper不为NULL,但调用Looper.myLooper()得到当前线程的Looper就有可能为NULL。
 
现在来看一个例子,模拟从网络获取数据,加载到ListView的过程:
  1 public class ListProgressDemo extends ListActivity { 
  2  
  3     @Override 
  4     public void onCreate(Bundle savedInstanceState) { 
  5         super.onCreate(savedInstanceState); 
  6         setContentView(R.layout.listprogress); 
  7  
  8         ((Button) findViewById(R.id.load_Handler)).setOnClickListener(new View.OnClickListener(){ 
  9  
 10             @Override 
 11             public void onClick(View view) { 
 12                 data = null; 
 13                 data = new ArrayList<String>(); 
 14  
 15                 adapter = null; 
 16  
 17                 showDialog(PROGRESS_DIALOG); 
 18                 new ProgressThread(handler, data).start(); 
 19             } 
 20         }); 
 21     } 
 22  
 23     @Override 
 24     protected Dialog onCreateDialog(int id) { 
 25         switch(id) { 
 26         case PROGRESS_DIALOG: 
 27                  return ProgressDialog.show(this, "",  
 28                    "Loading. Please wait...", true); 
 29  
 30         default: return null; 
 31         } 
 32     } 
 33  
 34     private class ProgressThread extends Thread { 
 35  
 36         private Handler handler; 
 37         private ArrayList<String> data; 
 38  
 39         public ProgressThread(Handler handler, ArrayList<String> data) { 
 40             this.handler = handler; 
 41             this.data = data; 
 42         } 
 43  
 44         @Override 
 45         public void run() { 
 46             for (int i=0; i<8; i++) { 
 47                 data.add("ListItem"); //后台数据处理
 48                 try { 
 49                     Thread.sleep(100); 
 50                 }catch(InterruptedException e) { 
 51                      
 52                     Message msg = handler.obtainMessage(); 
 53                     Bundle b = new Bundle(); 
 54                     b.putInt("state", STATE_ERROR); 
 55                     msg.setData(b); 
 56                     handler.sendMessage(msg);  
 57                      
 58                 } 
 59             } 
 60             Message msg = handler.obtainMessage(); 
 61             Bundle b = new Bundle(); 
 62             b.putInt("state", STATE_FINISH); 
 63             msg.setData(b); 
 64             handler.sendMessage(msg); 
 65         } 
 66          
 67     } 
 68  
 69     // 此处甚至可以不需要设置Looper,因为Handler默认就使用当前线程的Looper
 70     private final Handler handler = new Handler(Looper.getMainLooper()) {
 71  
 72         public void handleMessage(Message msg) { // 处理Message,更新ListView
 73             int state = msg.getData().getInt("state"); 
 74             switch(state){ 
 75                 case STATE_FINISH: 
 76                     dismissDialog(PROGRESS_DIALOG); 
 77                     Toast.makeText(getApplicationContext(), 
 78                             "加载完成!", 
 79                             Toast.LENGTH_LONG) 
 80                          .show(); 
 81  
 82                     adapter = new ArrayAdapter<String>(getApplicationContext(), 
 83                             android.R.layout.simple_list_item_1, 
 84                             data ); 
 85                              
 86                     setListAdapter(adapter); 
 87  
 88                     break; 
 89  
 90                 case STATE_ERROR: 
 91                    dismissDialog(PROGRESS_DIALOG); 
 92                    Toast.makeText(getApplicationContext(), 
 93                            "处理过程发生错误!", 
 94                            Toast.LENGTH_LONG) 
 95                         .show(); 
 96  
 97                    adapter = new ArrayAdapter<String>(getApplicationContext(), 
 98                            android.R.layout.simple_list_item_1, 
 99                            data ); 
100                             
101                       setListAdapter(adapter); 
102  
103                       break; 
104  
105                default: 
106  
107             } 
108         } 
109     }; 
110  
111  
112     private ArrayAdapter<String> adapter; 
113     private ArrayList<String> data; 
114  
115     private static final int PROGRESS_DIALOG = 1; 
116     private static final int STATE_FINISH = 1; 
117     private static final int STATE_ERROR = -1; 
118 } 

 

AsyncTask版:
 1 ((Button) findViewById(R.id.load_AsyncTask)).setOnClickListener(new View.OnClickListener(){ 
 2  
 3     @Override 
 4     public void onClick(View view) { 
 5         data = null; 
 6         data = new ArrayList<String>(); 
 7  
 8         adapter = null; 
 9  
10         //显示ProgressDialog放到AsyncTask.onPreExecute()里 
11         //showDialog(PROGRESS_DIALOG); 
12         new ProgressTask().execute(data); 
13     } 
14 }); 
15  
16 private class ProgressTask extends AsyncTask<ArrayList<String>, Void, Integer> { 
17  
18 /* 该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。*/ 
19 @Override 
20 protected void onPreExecute() { 
21     // 先显示ProgressDialog
22     showDialog(PROGRESS_DIALOG); 
23 } 
24  
25 /* 执行那些很耗时的后台计算工作。可以调用publishProgress方法来更新实时的任务进度。 */ 
26 @Override 
27 protected Integer doInBackground(ArrayList<String>... datas) { 
28     ArrayList<String> data = datas[0]; 
29     for (int i=0; i<8; i++) { 
30         data.add("ListItem"); 
31     } 
32     return STATE_FINISH; 
33 } 
34  
35 /* 在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用, 
36  * 后台的计算结果将通过该方法传递到UI thread. 
37  */ 
38 @Override 
39 protected void onPostExecute(Integer result) { 
40     int state = result.intValue(); 
41     switch(state){ 
42     case STATE_FINISH: 
43         dismissDialog(PROGRESS_DIALOG); 
44         Toast.makeText(getApplicationContext(), 
45                 "加载完成!", 
46                 Toast.LENGTH_LONG) 
47              .show(); 
48  
49         adapter = new ArrayAdapter<String>(getApplicationContext(), 
50                 android.R.layout.simple_list_item_1, 
51                 data ); 
52                  
53         setListAdapter(adapter); 
54  
55         break; 
56          
57     case STATE_ERROR: 
58        dismissDialog(PROGRESS_DIALOG); 
59        Toast.makeText(getApplicationContext(), 
60                "处理过程发生错误!", 
61                Toast.LENGTH_LONG) 
62             .show();
63  
64        adapter = new ArrayAdapter<String>(getApplicationContext(), 
65                android.R.layout.simple_list_item_1, 
66                data );
67  
68           setListAdapter(adapter);
69  
70           break;
71  
72    default:
73  
74    }
75 }

Android另外提供了一个工具类:AsyncTask。它使得UI thread的使用变得异常简单。它使创建需要与用户界面交互的长时间运行的任务变得更简单,不需要借助线程和Handler即可实现。

    1)  子类化AsyncTask
    2)  实现AsyncTask中定义的下面一个或几个方法
         onPreExecute() 开始执行前的准备工作;
         doInBackground(Params...) 开始执行后台处理,可以调用publishProgress方法来更新实时的任务进度;
         onProgressUpdate(Progress...)  在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
         onPostExecute(Result) 执行完成后的操作,传送结果给UI 线程。
 
         这4个方法都不能手动调用。而且除了doInBackground(Params...)方法,其余3个方法都是被UI线程所调用的,所以要求:
        1) AsyncTask的实例必须在UI thread中创建;
        2) AsyncTask.execute方法必须在UI thread中调用;
        
    同时要注意:该task只能被执行一次,否则多次调用时将会出现异常。而且是不能手动停止的,这一点要注意,看是否符合你的需求!