先看看這個介紹
http://www.cnblogs.com/coolszy/archive/2011/04/25/2026662.html
也就是這圖片:
說明一下:外部系統需要向某個android線程發送消息,必須通過屬於該androidthread的handler這個對象進行。
再看看這個例子
andriod提供了 Handler 和 Looper 來滿足線程間的通信。例如一個子線程從網絡上下載了一副圖片,當它下載完成後會發送消息給主線程,這個消息是通過綁定在主線程的Handler來傳遞的。
在Android,這裏的線程分爲有消息循環的線程和沒有消息循環的線程,有消息循環的線程一般都會有一個Looper,這個是android的新概念。我們的主線程(UI線程)就是一個消息循環的線程。針對這種消息循環的機制,我們引入一個新的機制Handler,我們有消息循環,就要往消息循環裏面發送相應的消息,自定義消息一般都會有自己對應的處理,消息的發送和清除,把這些都封裝在Handler裏面,注意Handler只是針對那 些有Looper的線程,不管是UI線程還是子線程,只要你有Looper,我就可以往你的消息隊列裏面添加東西,並做相應的處理。
但是這裏還有一點,就是只要是關於UI相關的東西,就不能放在子線程中,因爲子線程是不能操作UI的,只能進行數據、系統等其他非UI的操作。
一個Handler的創建它就會被綁定到這個線程的消息隊列中,如果是在主線程創建的,那就不需要寫代碼來創建消息隊列了,默認的消息隊列會在主線程被創建。但是如果是在子線程的話,就必須在創建Handler之前先初始化線程的消息隊列。如下面的代碼:
01 |
class
ChildThread extends
Thread { |
02 |
|
03 |
public void run() { |
04 |
|
05 |
/* |
06 |
* 創建 handler前先初始化Looper. |
07 |
*/ |
08 |
Looper.prepare(); |
09 |
|
10 |
/* |
11 |
* 在子線程創建handler,所以會綁定到子線程的消息隊列中 |
12 |
* |
13 |
*/ |
14 |
mChildHandler = new Handler() { |
15 |
|
16 |
public void handleMessage(Message msg) { |
17 |
|
18 |
/* |
19 |
* Do some expensive operations there. |
20 |
*/ |
21 |
} |
22 |
}; |
23 |
|
24 |
/* |
25 |
* 啓動該線程的消息隊列 |
26 |
*/ |
27 |
Looper.loop(); |
28 |
}
|
29 |
} |
當Handler收到消息後,就會運行handleMessage(…)的回調函數,可以在裏面做一些耗時的操作。
最後完成了操作要結束子線程時,記得調用quit()來結束消息循環隊列。
1 |
mChildHandler.getLooper().quit(); |
下面是一個線程間通信的小例子:
001 |
/** |
002 |
* |
003 |
* @author allin.dev |
005 |
* |
006 |
*/ |
007 |
public
class MainThread extends Activity { |
008 |
|
009 |
private static final String TAG = "MainThread" ; |
010 |
private Handler mMainHandler, mChildHandler; |
011 |
private TextView info; |
012 |
private Button msgBtn; |
013 |
|
014 |
@Override |
015 |
public void onCreate(Bundle savedInstanceState) { |
016 |
super .onCreate(savedInstanceState); |
017 |
setContentView(R.layout.main); |
018 |
|
019 |
info = (TextView) findViewById(R.id.info); |
020 |
msgBtn = (Button) findViewById(R.id.msgBtn); |
021 |
|
022 |
mMainHandler = new Handler() { |
023 |
|
024 |
@Override |
025 |
public void handleMessage(Message msg) { |
026 |
Log.i(TAG, "Got an incoming message from the child thread - " |
027 |
+ (String) msg.obj); |
028 |
// 接收子線程的消息 |
029 |
info.setText((String) msg.obj); |
030 |
} |
031 |
|
032 |
}; |
033 |
|
034 |
new ChildThread().start(); |
035 |
|
036 |
|
037 |
msgBtn.setOnClickListener( new OnClickListener() { |
038 |
|
039 |
@Override |
040 |
public void onClick(View v) { |
041 |
|
042 |
if (mChildHandler != null ) { |
043 |
|
044 |
//發送消息給子線程 |
045 |
Message childMsg = mChildHandler.obtainMessage(); |
046 |
childMsg.obj = mMainHandler.getLooper().getThread().getName() + " says Hello" ; |
047 |
mChildHandler.sendMessage(childMsg); |
048 |
|
049 |
Log.i(TAG, "Send a message to the child thread - " + (String)childMsg.obj); |
050 |
|
051 |
|
052 |
} |
053 |
} |
054 |
}); |
055 |
|
056 |
}
|
057 |
|
058 |
public void onDestroy() { |
059 |
super .onDestroy(); |
060 |
Log.i(TAG, "Stop looping the child thread's message queue" ); |
061 |
|
062 |
mChildHandler.getLooper().quit(); |
063 |
}
|
064 |
|
065 |
class ChildThread extends Thread { |
066 |
|
067 |
private static final String CHILD_TAG = "ChildThread" ; |
068 |
|
069 |
public void run() { |
070 |
this .setName( "ChildThread" ); |
071 |
|
072 |
//初始化消息循環隊列,需要在Handler創建之前 |
073 |
Looper.prepare(); |
074 |
|
075 |
mChildHandler = new Handler() { |
076 |
@Override |
077 |
public void handleMessage(Message msg) { |
078 |
Log.i(CHILD_TAG, "Got an incoming message from the main thread - " + (String)msg.obj); |
079 |
|
080 |
|
081 |
try { |
082 |
|
083 |
//在子線程中可以做一些耗時的工作 |
084 |
sleep( 100 ); |
085 |
|
086 |
Message toMain = mMainHandler.obtainMessage(); |
087 |
toMain.obj = "This is " + this .getLooper().getThread().getName()
+ |
088 |
". Did you send me \"" + (String)msg.obj + "\"?" ; |
089 |
|
090 |
mMainHandler.sendMessage(toMain); |
091 |
|
092 |
Log.i(CHILD_TAG, "Send a message to the main thread - " + (String)toMain.obj); |
093 |
|
094 |
} catch (InterruptedException e) { |
095 |
// TODO Auto-generated catch block |
096 |
e.printStackTrace(); |
097 |
} |
098 |
} |
099 |
|
100 |
}; |
101 |
|
102 |
Log.i(CHILD_TAG, "Child handler is bound to - " + mChildHandler.getLooper().getThread().getName()); |
103 |
|
104 |
//啓動子線程消息循環隊列 |
105 |
Looper.loop(); |
106 |
} |
107 |
}
|
108 |
} |