转自:http://www.android1.net/

高煥堂的第4本書精美印刷出來囉!!!

PS.========== News ========================

1. 高煥堂的Android培訓課程,請看www.misoo1.com

2. 高煥堂的第4本 Android書籍:<<Android 設計招式之美>>

將於下週上市,請到重慶南路天瓏書店購買。

========== News ========================

<<<本文>>>

1.Message Queue的角色

l在你的Android程式裡,新誕生一個線程,或稱執行緒(Thread)時,並不會自動建立其Message Loop

lAndroid裡並沒有GlobalMessage Queue資料結構,例如,不同APK裡的物件不能透過Massage Queue來交換訊息(Message)

l一個線程可以誕生一個Looper之物件,由它來管理此線程裡的Message Queue

l你可以誕生Handler之物件來與Looper溝通,以便push新訊息到Message Queue裡;或者接收Looper(Message Queue取出)所送來的訊息。

l線程AHandler物件參考可以傳遞給別的線程,讓別的線程BC等能送訊息來給線程A(存於AMessage Queue)

l線程AMessage Queue裡的訊息,只有線程A所屬的物件可以處理之。

l使用Looper.myLooper可以取得目前線程的Looper物件參考值。

l使用mHandler =newEevntHandler(Looper.myLooper());可誕生用來處理目前線程的Handler物件;其中,EevntHandlerHandler的子類別。

l使用mHandler =newEevntHandler(Looper.getMainLooper());可誕生用來處理main線程的Handler物件;其中,EevntHandlerHandler的子類別。

2.範例之一:Looper物件之角色

Looper類別用來管理特定線程內物件之間的訊息交換(Message Exchange)。你的應用程式可以誕生許多個線程,或稱執行緒(Thread)。而一個線程可以誕生許多個物件,這些物件之間常常需要互相交換訊息。如果有這種需要,您可以替線程誕生一個Looper類別之物件,來擔任訊息交換的管理工作。Looper物件會建立一個MessageQueue資料結構來存放各物件傳來的訊息(包括UI事件或System事件等)。如下圖:

每一個線程(Thread,或稱「執行緒」)裡可含有一個Looper物件以及一個MessageQueue資料結構。在你的應用程式裡,可以定義Handler的子類別來接收Looper所送出的訊息。

//----- Looper_01範例-----

packagecom.misoo.kx04;

importandroid.app.Activity;

importandroid.graphics.Color;

importandroid.os.Bundle;

importandroid.os.Handler;

importandroid.os.Looper;

importandroid.os.Message;

importandroid.view.View;

importandroid.view.View.OnClickListener;

importandroid.widget.Button;

importandroid.widget.LinearLayout;

importandroid.widget.TextView;

publicclassac01extendsActivityimplementsOnClickListener {

privatefinalintWC= LinearLayout.LayoutParams.WRAP_CONTENT;

privatefinalintFP= LinearLayout.LayoutParams.FILL_PARENT;

publicTextViewtv;

privateEventHandlermHandler;

privateButtonbtn,btn2,btn3;

publicvoidonCreate(Bundle icicle) {

super.onCreate(icicle);

LinearLayout layout =newLinearLayout(this);

layout.setOrientation(LinearLayout.VERTICAL);

btn=newButton(this);

btn.setId(101);

btn.setBackgroundResource(R.drawable.heart);

btn.setText("test looper");

btn.setOnClickListener(this);

LinearLayout.LayoutParams param =

newLinearLayout.LayoutParams(100,50);

param.topMargin= 10;

layout.addView(btn, param);

btn2=newButton(this);

btn2.setId(102);

btn2.setBackgroundResource(R.drawable.ok_blue);

btn2.setText("exit");

btn2.setOnClickListener(this);

layout.addView(btn2, param);

tv=newTextView(this);

tv.setTextColor(Color.WHITE);

tv.setText("");

LinearLayout.LayoutParams param2 =

newLinearLayout.LayoutParams(FP,WC);

param2.topMargin= 10;

layout.addView(tv, param2);

setContentView(layout);

}

publicvoidonClick(View v) {

switch(v.getId()){

case101:

Looper looper;

looper = Looper.myLooper();

mHandler=newEventHandler(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;

case102:

finish();

break;

}

}

//------------------------------------------------------

classEventHandlerextendsHandler

{

publicEventHandler(Looper looper) {

super(looper);

}

@Override

publicvoidhandleMessage(Message msg) {

tv.setText((String)msg.obj);

}

}

}

//-------------------------------------------------------

說明:

此程式啟動時,目前線程(即主線程, main thread)已誕生了一個Looper物件,並且有了一個MessageQueue資料結構。

指令:looper = Looper.myLooper();

就呼叫Looper類別的靜態myLooper()函數,以取得目前線程裡的Looper物件之參考值。

指令:mHandler=newEventHandler(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範例-----

packagecom.misoo.kx04;

importandroid.app.Activity;

importandroid.graphics.Color;

importandroid.os.Bundle;

importandroid.os.Handler;

importandroid.os.Looper;

importandroid.os.Message;

importandroid.view.View;

importandroid.view.View.OnClickListener;

importandroid.widget.Button;

importandroid.widget.LinearLayout;

importandroid.widget.TextView;

publicclassac01extendsActivityimplementsOnClickListener {

privatefinalintWC= LinearLayout.LayoutParams.WRAP_CONTENT;

privatefinalintFP= LinearLayout.LayoutParams.FILL_PARENT;

publicTextViewtv;

privatemyThreadt;

privateButtonbtn,btn2,btn3;

publicvoidonCreate(Bundle icicle) {

super.onCreate(icicle);

LinearLayout layout =newLinearLayout(this);

layout.setOrientation(LinearLayout.VERTICAL);

btn=newButton(this);

btn.setId(101);

btn.setBackgroundResource(R.drawable.heart);

btn.setText("test looper");

btn.setOnClickListener(this);

LinearLayout.LayoutParams param =

newLinearLayout.LayoutParams(100,50);

param.topMargin= 10;

layout.addView(btn, param);

btn2=newButton(this);

btn2.setId(102);

btn2.setBackgroundResource(R.drawable.ok_blue);

btn2.setText("exit");

btn2.setOnClickListener(this);

layout.addView(btn2, param);

tv=newTextView(this);

tv.setTextColor(Color.WHITE);

tv.setText("");

LinearLayout.LayoutParams param2 =

newLinearLayout.LayoutParams(FP,WC);

param2.topMargin= 10;

layout.addView(tv, param2);

setContentView(layout);

}

publicvoidonClick(View v) {

switch(v.getId()){

case101:

t=newmyThread();

t.start();

break;

case102:

finish();

break;

}

}

//------------------------------------------------------

classEHandlerextendsHandler {

publicEHandler(Looper looper) {

super(looper);

}

@Override

publicvoidhandleMessage(Message msg) {

tv.setText((String)msg.obj);

}

}

//------------------------------------------------------

classmyThreadextendsThread{

privateEHandlermHandler;

publicvoidrun() {

Looper myLooper, mainLooper;

myLooper = Looper.myLooper();

mainLooper = Looper.getMainLooper();

String obj;

if(myLooper ==null){

mHandler=newEHandler(mainLooper);

obj ="current thread has no looper!";

}

else{

mHandler=newEHandler(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 =newEHandler(mainLooper);mHandler屬於主線程。

指令:mHandler.sendMessage(m);

就將m訊息存入到主線程的Message Queue裡。mainLooper看到Message Queue裡有訊息,就會處理之,於是由主線程執行到mHandlerhandleMessage()函數來處理訊息。此程式輸出畫面為:

4.結語:

lMessage Loop的用途很廣。請你參閱高煥堂所寫的Android系列書籍,尤其是其中的第4本書:<<Android設計招式之美>>

l以上只是本文的前半段而已,請你繼續閱讀後半段。

---- END ---

更多相关文章

  1. ESC/POS指令集在Android设备上使用实例(通过socket)
  2. Android 应用程式的基本档案结构
  3. 一鍵ROOT機的Android程式《Universal Androot》
  4. Android 获取CPU架构(指令集)
  5. 无废话Android之常见adb指令、电话拨号器、点击事件的4种写法、
  6. android 几个快速编译image的指令
  7. Android-SQLite3基本操作指令集合
  8. Android Studio如何配置CURL指令一键打包apk上传至蒲公英

随机推荐

  1. 中国的 Android:尚未发掘的应用市场?
  2. 做好准备,让你的短信应用迎接Android(安卓
  3. android开发——通过子线程更新界面UI
  4. Android 内功心法(1.2)——android常用设
  5. Android系统信息获取 之十二:获取屏幕分辨
  6. Android 自定义组件
  7. android 模拟器的使用(Android模拟器介绍
  8. Android加载Gif图片的一般方法:Movie实现
  9. Android初学的学习笔记
  10. 2019AndroidBAT.字节跳动74道高级面试第