[java] view plain copy print ? java
<EMBED id=ZeroClipboardMovie_1 height=14 name=ZeroClipboardMovie_1 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=29 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=1&width=29&height=14" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">android
網上以文檔形式流傳,不知道原文在哪,感謝原做者了! web
================簡單調整了下格式就共享了===============================================安全
對於Android的Message機制主要涉及到三個主要的類,分別是Handler、Message、Looper;首先對每一個類作一個簡單介紹;而後再介紹所謂的Android的Message機制是如何實現的,最後給了一個示例。app
1、介紹三個相關的類異步
一、 Handler主要有兩個用途:首先是能夠定時處理或者分發消息,其次是能夠添加一個執行的行爲在其它線程中執行,ide
對於Handler中的方法,能夠選擇你關心的操做去覆蓋它,處理具體的業務操做,常見的就是對消息的處理能夠覆蓋public voidhandleMessage(參數)方法,能夠根據參數選擇對此消息是否須要作出處理,這個和具體的參數有關。例以下代碼:函數
[java] view plain copy print ? oop
<EMBED id=ZeroClipboardMovie_2 height=14 name=ZeroClipboardMovie_2 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=29 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=2&width=29&height=14" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">post
Handler mHandler = new Handler() {
@Override public void handleMessage(Message msg) {//覆蓋handleMessage方法
switch (msg.what) {//根據收到的消息的what類型處理
case BUMP_MSG:
Log.v("handler", "Handler===="+msg.arg1);//打印收到的消息
break;
default:
super.handleMessage(msg);//這裏最好對不須要或者不關心的消息拋給父類,避免丟失消息
break;
}
}
};
二、 消息android.os.Message
android.os.Message是定義一個Messge包含必要的描述和屬性數據,而且此對象能夠被髮送給android.os.Handler處理。屬性字段:arg一、arg二、what、obj、replyTo等;其中arg1和arg2是用來存放整型數據的;what是用來保存消息標示的;obj是Object類型的任意對象;replyTo是消息管理器,會關聯到一個handler,handler就是處理其中的消息。一般對Message對象不是直接new出來的,只要調用handler中的obtainMessage方法來直接得到Message對象。
三、 Looper類主要用於一個線程循環獲取消息隊列中的消息。
Looper的做用主要是負責管理消息隊列,負責消息的出列和入列操做。
2、Android的Message機制是如何實現?
一、爲何要使用Message機制主要是爲了保證線程之間操做安全,同時不須要關心具體的消息接收者,使消息自己和線程剝離開,這樣就能夠方便的實現定時、異步等操做。
二、Message機制原理示意圖:
Activity <---------------> EHandler<-----> Looper<-----> MessageQueue
IntentReceiver <-----> EHandler <-----> Looper<-----> MessageQueue
圖 1
三、 如何實現?(具體描述上圖的消息流的過程)
實現Message機制須要Handler、Message、Looper三個之間的互相做用來實現;當線程A須要發消息給線程B的時候,線程B要用本身的Looper實例化Handler類,就是構造handler對象時,把當前線程的Looper傳給Handler構造函數,handler自己會保存對Looper的引用,handler構造好之後,就能夠用handler的obtainMessage方法實例化Message對象,只要把要傳的數據給Handler,Handler就會構造Message對象,而且把Message對象添加到消息隊列裏面。而後就能夠調用handler的sendMessage方法把Message對象發送出去,Looper就把消息放到消息隊列中;最後當Looper知道消息隊列不爲空時候,就會循環的從消息隊列中取消息,取出消息就會調用剛纔實例化好的Handler對象的handleMessage方法取處理消息,整個Message過程就是這樣。(如圖1所示)
3、下面介紹一個關於Message機制的簡單的示例,具體的代碼以下:
一、 下面是一個新起的一個線程發消息的示例
handler自己不只能夠發送消息,還能夠用post的方式添加一個實現Runnable接口的匿名對象到消息隊列中,在目標收到消息後就能夠回調的方式在本身的線程中執行run的方法體,這就是handler兩種典型的使用方式!
[java] view plain copy print ?
<EMBED id=ZeroClipboardMovie_3 height=14 name=ZeroClipboardMovie_3 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=29 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=3&width=29&height=14" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">
class NoLooperThread extends Thread {
private EventHandler mNoLooperThreadHandler;
public void run() {
Looper myLooper, mainLooper;
myLooper= Looper.myLooper(); //得到本身的Looper
mainLooper= Looper.getMainLooper(); //得到本身的main的looper
String obj;
if (myLooper == null) {
mNoLooperThreadHandler = new EventHandler(mainLooper);
obj= "NoLooperThread has no looper andhandleMessage function executed in main thread!";
}else
{
mNoLooperThreadHandler = new EventHandler(myLooper);
obj= "This is from NoLooperThread self andhandleMessage function executed in NoLooperThread!";
}
mNoLooperThreadHandler.removeMessages(0); //清空消息隊列
if (false == postRunnable) {
Message m = mNoLooperThreadHandler.obtainMessage(2, 1, 1, obj); //生成消息對象
mNoLooperThreadHandler.sendMessage(m); //發送消息
Log.e(sTag, "NoLooperThread id:" + this.getId());
}else {
mNoLooperThreadHandler.post(new Runnable() { //添加一個Runnable接口的實現到消息隊列,此Runnable接口的實現不在此 線程中執行,會在接收的線程中執行。
public void run() {
tv.setText("update UI through handler post runnalbe mechanism!");
noLooerThread.stop();
}
});
}
}
二、下面是一個定時循環發消息的示例,以下代碼:
詳細的解釋參考代碼的註釋
Handler handler = new Handler() { //建立處理對象handler
publicvoid handleMessage(Message msg) {
switch (msg.what) {
caseMES: {
final int N = mCallbacks.beginBroadcast(); //Copy一份回調list,而且標記一個狀態
for (int i = 0; i <N; i++) {
try {
mCallbacks.getBroadcastItem(i).getValue(mMediaPlayer01.getCurrentPosition()); //遍歷全部回調接口 }catch (Exception e) {
e.printStackTrace();
}
}
mCallbacks.finishBroadcast(); //完成後狀態復位
sendMessageDelayed(obtainMessage(MES),1 * 1000);
}
break;
default:
super.handleMessage(msg);
}
}
};
NOTE: 整個hadleMessage方法至關一個嵌套的循環
4、總結:
所謂的消息機制其實很簡單,實現這種機制須要只須要四步:
一、實例化Looper(由於實例化Handler時須要一個looper);
二、實例化Handler,這裏須要覆蓋handleMessage方法,處理收到的消息;
三、 實例化Message對象,調用已經實例化好的handler對象的obtainMessage方法,把數據傳給obtainMessage方法,obtainMessage方法就會實例化一個Message對象。(這裏也能夠發送實現Runnable接口的對象);
四、調用Handler的sendMessage方法把實例化好的Message對象發送出去。
對每一個線程過程都是同樣的,只要按照上面的四個步驟來就能夠發送和接收消息了。