1.??Message Queue 的角色
l ??? 在你的 Android 程序里,新創建一個線程,或稱線程 (Thread) 時,并不會自動建立其 Message Loop 。
l ??? Android 里并沒有 Global 的 Message Queue 數據結構,例如,不同 APK 里的對象不能透過 Massage Queue 來交換消息 (Message) 。
l ??? 一個線程可以創建一個 Looper 對象,由它來管理此線程里的 Message Queue 。
l ??? 你可以創建 Handler 對象來與 Looper 溝通,以便 push 新消息到 Message Queue 里或者接收 Looper( 從 Message Queue 取出 ) 所送來的消息。
l ??? 線程 A 的 Handler 對象引用可以傳遞給別的線程,讓別的線程 B 或 C 等能發送消息來給線程 A( 存于 A 的 Message Queue 里 ) 。
l ??? 線程 A 的 Message Queue 里的消息,只有線程 A 所屬的對象可以處理之。
l ??? 使用 Looper.myLooper 可以取得目前線程的 Looper 對象引用。
l ??? 使用 mHandler =? new ?EventHandler(Looper. myLooper ()) ; 可創建用來處理目前線程的 Handler 對象;其中, EventHandler 是 Handler 的子類別。
l ??? 使用 mHandler =? new ?EventHandler(Looper. getMainLooper() ) ; 可創建用來處理 main 線程的 Handler 對象;其中, EventHandler 是 Handler 的子類別。
?
2.? 范例之一: Looper 類之角色
Looper 類別用來管理特定線程內對象之間的消息交換 (Message Exchange) 。你的應用程序可以創建許多個線程,或稱線程 (Thread) 。而一個線程可以實例化許多個對象,這些對象之間常常需要互相交換消息。如果有這種需要,您可以替線程創建一個 Looper 類對象,來處理信息交換的管理工作。 Looper 對象會建立一個 MessageQueue 數據結構來存放各對象傳來的消息 ( 包括 UI 事件或 System 事件等 ) 。如下圖:
?
?
?? 每一個線程 (Thread ,或稱「線程」 ) 里可含有一個 Looper 對象以及一個 MessageQueue 數據結構 。在你的應用程序里,可以 定義 Handler 的子類別來接收 Looper 所送出的消息 。
?
//----- Looper_01 范例 ?-----
package ?com.misoo.kx04;
import ?android.app.Activity;
import ?android.graphics.Color;
import ?android.os.Bundle;
import ?android.os.Handler;
import ?android.os.Looper;
import ?android.os.Message;
import ?android.view.View;
import ?android.view.View.OnClickListener;
import ?android.widget.Button;
import ?android.widget.LinearLayout;
import ?android.widget.TextView;
?
public ? class ?ac01? extends ?Activity? implements ?OnClickListener {
???? private ? final ? int ? WC ?= LinearLayout.LayoutParams. WRAP_CONTENT ;
???? private ? final ? int ? FP ?= LinearLayout.LayoutParams. FILL_PARENT ;
???? public ?TextView? tv ;
???? private ?EventHandler? mHandler ;
???? private ?Button? btn ,? btn2 ,? btn3 ;
???
???? public ? void ?onCreate(Bundle icicle) {
???????? super .onCreate(icicle);
????????LinearLayout layout =? new ?LinearLayout( this );
????????layout.setOrientation(LinearLayout. VERTICAL );
??????????????????????????????
???????? btn ?=? new ?Button( this );
???????? btn .setId(101);
???????? btn .setBackgroundResource(R.drawable. heart );
???????? btn .setText( "test looper" );
???????? btn .setOnClickListener( this );
????????LinearLayout.LayoutParams param = new ?LinearLayout.LayoutParams(100,50);
????????param. topMargin ?= 10;
????????layout.addView( btn , param);
???????????????
???????? btn2 ?=? new ?Button( this );
???????? btn2 .setId(102);
???????? btn2 .setBackgroundResource(R.drawable. ok_blue );
???????? btn2 .setText( "exit" );
???????? btn2 .setOnClickListener( this );
????????layout.addView( btn2 , param);
???????????????
???????? tv ?=? new ?TextView( this );
???????? tv .setTextColor(Color. WHITE );
???????? tv .setText( "" );
????????LinearLayout.LayoutParams param2 = new ?LinearLayout.LayoutParams( FP ,? WC );
????????param2. topMargin ?= 10;
????????layout.addView( tv , param2);
????????setContentView(layout);?????
????}
???????? public ? void ?onClick(View v) {
??????????? switch (v.getId()){
?????????????? case ?101: Looper looper;
??????????????????? looper = Looper. myLooper ();
??????????????????? mHandler ?=? new ?EventHandler(looper);
??????????????????? mHandler .removeMessages(0);
???????????????????? //? 清除整個 MessageQueue 里的事件,確保不會通知到別人
????????????????????String obj =? "This my message!" ;
????????????????????Message m =? mHandler .obtainMessage(1, 1, 1, obj);
???????????????????? //? 組裝成一個 Message 物件
???????????????????? mHandler .sendMessage(m);
???????????????????? //? 將 Message 物件送入 MessageQueue 里
??????????????????? ?? break ;
??????????????? case ?102:
??????????????????finish();
?????????????????? break ;
??????????}
???}
//------------------------------------------------------?????????????
class ?EventHandler? extends ?Handler{
???? public ?EventHandler(Looper looper) {
??????? super (looper);
????}
???? @Override
???? public ? void ?handleMessage(Message msg) {
???????? tv .setText((String)msg. obj );
????}
??}
}
//-------------------------------------------------------
說明:
?? 程序啟動時,當前線程 ( 即主線程 , main thread) 已創建了一個 Looper 對象,并且有了一個 MessageQueue 數據結構。
?? 指令: looper = Looper. myLooper (); 調用 Looper 類的靜態 myLooper() 函數,以取得目前線程里的 Looper 對象引用。
指令: mHandler ?=? new ?EventHandler(looper); 創建 一個 EventHandler 對象來與 Looper 溝通。 Activity 等對象可以通過 EventHandler 對象來將消息傳給 Looper ,然后放入 MessageQueue 里; EventHandler 對象也扮演 Listener 的角色,可接收 Looper 對象所送來的消息。如下圖:
?
?
指令: Message m =? mHandler .obtainMessage(1, 1, 1, obj); ? 先創建一個 Message 對象,并將數據存入次對象里。
指令: mHandler .sendMessage(m); ? 通過 mHandler 對象而將消息 m 傳給 Looper ,然后放入 MessageQueue 里。
此時 Looper 對象看到 MessageQueue 里有消息 m , 就將它廣播出去 , mHandler 對象接到此消息時,會調用其 handleMessage() 函數來處理之,于是輸出 "This my message!" 于畫面上,如下:
?
?
?
3.? 范例之二:由別的線程發送到主線程的 Message Queue
?
//----- Looper_02 范例 ?-----
package ?com.misoo.kx04;
import ?android.app.Activity;
import ?android.graphics.Color;
import ?android.os.Bundle;
import ?android.os.Handler;
import ?android.os.Looper;
import ?android.os.Message;
import ?android.view.View;
import ?android.view.View.OnClickListener;
import ?android.widget.Button;
import ?android.widget.LinearLayout;
import ?android.widget.TextView;
?
public ? class ?ac01? extends ?Activity? implements ?OnClickListener {
??????????? private ? final ? int ? WC ?= LinearLayout.LayoutParams. WRAP_CONTENT ;
??????????? private ? final ? int ? FP ?= LinearLayout.LayoutParams. FILL_PARENT ;
??????????? public ?TextView? tv ;
???? private ?myThread? t ;
???? private ?Button? btn ,? btn2 ,? btn3 ;
???
???? public ? void ?onCreate(Bundle icicle) {
???????????????? //文章長度有限,代碼請參考上例
???????????????}
?????????????? public ? void ?onClick(View v) {
????????????????????? switch (v.getId()){
????????????????????? case ?101:
??????????????????????? t ?=? new ?myThread();
??????????????????????? t .start();
??????????????????????? break ;
????????????????????? case ?102:
?????????????????? ?????????? finish();
??????????????????????? break ;
?????????????????????}
???????????}
//------------------------------------------------------?????????????
class ?EHandler? extends ?Handler {???????????????????????????????????? //文章長度有限,代碼請參考上例
?? //------------------------------------------------------?????????????
class ?myThread? extends ?Thread{
???????????? private ?EHandler? mHandler ;
public ? void ?run() {
????????????????Looper myLooper, mainLooper;
????????????????myLooper = Looper. myLooper ();
????????????????mainLooper = Looper. getMainLooper ();
????????????????String obj;
???????????????? if (myLooper ==? null ){
??????????????????????? mHandler ?=? new ?EHandler(mainLooper);
???????????????????????obj =? "current thread has no looper!" ;
????????????????}
???????????????? else ?{
????????????????????? mHandler ?=? new ?EHandler(myLooper);
?????????????????????obj =? "This is from current thread." ;
????????????????}
???????????????? mHandler .removeMessages(0);
????????????????Message m =? mHandler .obtainMessage(1, 1, 1, obj);
???????????????? mHandler .sendMessage(m);
?????????????}
??}
}
?
?
Android 會自動替主線程建立 Message Queue 。 在這個 子線程里并沒有建立 Message Queue 。所以, myLooper 值為 null ,而 mainLooper 則指向主線程里的 Looper 對象。于是,執行到指令:
mHandler =? new ?EHandler(mainLooper);? 此 mHandler 屬于主線程 。
指令: mHandler .sendMessage(m);
就將消息 m 存入到主線程的 Message Queue 里。 mainLooper 看到 Message Queue 里有消息,就會處理之,于是由主線程執行到 mHandler 的 handleMessage() 函數來處理消息。此程序輸出畫面為:
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
