1. 程式人生 > >Android的Message機制(簡單小結)

Android的Message機制(簡單小結)

網上以文件形式流傳,不知道原文在哪,感謝原作者了!

================簡單調整了下格式就共享了===============================================

對於Android的Message機制主要涉及到三個主要的類,分別是Handler、Message、Looper;首先對每個類做一個簡單介紹;然後再介紹所謂的Android的Message機制是如何實現的,最後給了一個示例。

一、介紹三個相關的類

1、 Handler主要有兩個用途:首先是可以定時處理或者分發訊息,其次是可以新增一個執行的行為在其它執行緒中執行,

對於Handler中的方法,可以選擇你關心的操作去覆蓋它,處理具體的業務操作,常見的就是對訊息的處理可以覆蓋public void

handleMessage(引數)方法,可以根據引數選擇對此訊息是否需要做出處理,這個和具體的引數有關。例如下程式碼:

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;
	}
}
};


2、 訊息android.os.Message

android.os.Message是定義一個Messge包含必要的描述和屬性資料,並且此物件可以被髮送給android.os.Handler處理。屬性欄位:arg1、arg2、what、obj、replyTo等;其中arg1和arg2是用來存放整型資料的;what是用來儲存訊息標示的;obj是Object型別的任意物件;replyTo是訊息管理器,會關聯到一個handler,handler就是處理其中的訊息。通常對Message物件不是直接new出來的,只要呼叫handler中的obtainMessage方法來直接獲得Message物件。

3、 Looper類主要用於一個執行緒迴圈獲取訊息佇列中的訊息。

Looper的作用主要是負責管理訊息佇列,負責訊息的出列和入列操作。

二、Android的Message機制是如何實現?

1、為什麼要使用Message機制主要是為了保證執行緒之間操作安全,同時不需要關心具體的訊息接收者,使訊息本身和執行緒剝離開,這樣就可以方便的實現定時、非同步等操作。

2、Message機制原理示意圖:

Activity   <--------------->  EHandler<----->  Looper<----->  MessageQueue     

IntentReceiver <----->  EHandler <----->  Looper<----->  MessageQueue       

                                                                                           圖 1

3、 如何實現?(具體描述上圖的訊息流的過程)

實現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所示)

三、下面介紹一個關於Message機制的簡單的示例,具體的程式碼如下:

1、 下面是一個新起的一個執行緒發訊息的示例

handler本身不僅可以傳送訊息,還可以用post的方式新增一個實現Runnable介面的匿名物件到訊息佇列中,在目標收到訊息後就可以回撥的方式在自己的執行緒中執行run的方法體,這就是handler兩種典型的使用方式!

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();
						}
            		});
   			}
}


2、下面是一個定時迴圈發訊息的示例,如下程式碼:

詳細的解釋參考程式碼的註釋

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方法相當一個巢狀的迴圈

四、總結:

所謂的訊息機制其實很簡單,實現這種機制需要只需要四步:

     1、例項化Looper(因為例項化Handler時需要一個looper);

     2、例項化Handler,這裡需要覆蓋handleMessage方法,處理收到的訊息;

     3、 例項化Message物件,呼叫已經例項化好的handler物件的obtainMessage方法,把資料傳給obtainMessage方法,obtainMessage方法就會例項化一個Message物件。(這裡也可以傳送實現Runnable介面的物件);

     4、呼叫Handler的sendMessage方法把例項化好的Message物件傳送出去。

對每個執行緒過程都是一樣的,只要按照上面的四個步驟來就可以傳送和接收訊息了。


相關推薦

Android的Message機制簡單小結

網上以文件形式流傳,不知道原文在哪,感謝原作者了! ================簡單調整了下格式就共享了=============================================== 對於Android的Message機制主要涉及到三個主要的類,分

初識nginx反向代理和緩存機制簡單實現

修改 請求轉發 b- nginx bin text pan types con 實現的需求圖: 環境: nginx緩存和反向代理服務器:192.168.0.224 實際存儲數據機器:192.168.0.37 一、實現反向代理 1、安裝nginx,兩臺服務器

java序列化機制簡單使用

轉載:孤傲蒼狼 https://www.cnblogs.com/xdp-gacl/p/3777987.html 詳細分析:http://www.importnew.com/24490.html 一、序列化和反序列化的概念   把物件轉換為位元組序列的過程稱為物件的序列化。   

Unity實現自己的事件機制簡單實現

事件機制廣泛應用於mvc模式中,靈活的事件機制能夠彌補Unity中的一些缺陷,比如協程的執行。因為協程不能返回值,也不能通過out或者ref傳遞。通過事件機制,可以知道協程執行進度並且返回執行結果。當然,這只是個舉例,也只是我習慣用的一種方式。如果有更好的實現方式,希望不吝

RecyclerView複用ViewHolder機制簡單瞭解

本文特別low我設定item為200dp,列印20個,發現onCreateViewHolder僅僅執行了9次int i = 0; @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup par

用Linux C的互斥鎖機制解決哲學家就餐問題簡單實現

    在1971年,著名的電腦科學家艾茲格·迪科斯徹提出了一個同步問題,即假設有五臺計算機都試圖訪問五份共享的磁帶驅動器。稍後,這個問題被託尼·霍爾重新表述為哲學家就餐問題。這個問題可以用來解釋死鎖和資源耗盡。    「哲學家就餐說明」:有五個哲學家共用一張圓桌,分別坐在

uva 10474 Where is the Marble?簡單

content mil stdlib.h std lib [0 數據 main pre 我非常奇怪為什麽要把它歸類到回溯上,明明就是簡單排序,查找就OK了。wa了兩次,我還非常不解的懷疑了為什麽會 wa,原來是我居然把要找的數字也排序了,當時僅僅是想著能快一點查找。所以

POJ 1321 棋盤問題簡單DFS

clas mission sample 標記 span ssi algo std spa                                                           棋盤問題 Time Limit: 1000MS

POJ 1979 Red and Black簡單DFS

either www enter ont false num present direction roo Red and Black Description There is a rectangular room, covered with square tile

UVa 12716 GCD XOR 簡單證明

i++ map esp typedef -a type print const max 題意: 問 gcd(i,j) = i ^ j 的對數(j <=i <= N ) N的範圍為30000000,有10000組例子 思路:GCD(a,b) = a^b =

lightoj 1036 - A Refining Company簡單dp

esp scan blank 最大值 typedef 轉移 iostream ret for 題目鏈接:http://www.lightoj.com/volume_showproblem.php?problem=1036 題解:設dp[i][j]表示處理到(i,j)

第十一章 springboot + mongodb簡單查詢

req all bool pan 可能 set 如果 創建 使用 1、mongodb在mac上的安裝 下載mongodb,https://www.mongodb.org/ 解壓縮到一個指定文件夾,如:/Users/enniu1/Desktop/zjg/mongodb

一種排序nyoj8簡單排序

scan http -a tdi 輸入 clu truct clr -c 一種排序 時間限制:3000 ms | 內存限制:65535 KB 難度:3 描寫敘述如今有非常多長方形。每個長方形都有一個編號,這個編號能夠反復。還知道

bootstrap modal垂直居中簡單封裝

math str class ria extend splay play 觸發 代碼 未封裝前: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"&

Codeforces 456C - Boredom簡單DP

eof size com 數值 content -s rom hat 16px Alex doesn‘t like boredom. That‘s why whenever he gets bored, he comes up with game

HDU 2102 A計劃簡單DFS

ont inpu clu 通過 csdn input tin 一次 != Description 可憐的公主在一次次被魔王擄走一次次被騎士們救回來之後,而今,不幸的她再一次面臨生命的考驗。魔王已經發出消息說將在T時刻吃掉公主,因為他聽信謠言說吃公主的肉也能長生不老。年邁的國

Java 垃圾回收機制早期版本

重新 速度 交互 綜合 技術 -1 遍歷 我們 後臺 Java 垃圾回收機制在我們普通理解來看,應該視為一種低優先級的後臺進程來實現的,其實早期版本的Java虛擬機並非以這種方式實現的。 先從一種很簡單的垃圾回收方式開始。 引用計數   引用計數是一種簡單但是速度很慢

POJ 2229 Sumsets簡單DP

nbsp 自己 arc arm 相加 res sum name base Farmer John commanded his cows to search for different sets of numbers that sum to a given number.

POJ 2385 Apple Catching簡單DP

app details ostream 鍛煉 six ack can pre using It is a little known fact that cows love apples. Farmer John has two apple trees (which a

大魚吃小魚簡單模擬

一個 入棧 nco http spa println code tar pre 題目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1289 從左往右將數字壓入棧裏(想象成一個水平向右的棧),如果