Dalvik/ART(ANDROID)中的多线程机制(1)
Google參考了Windows的消息處理機制,在Android系統中實現了一套類似的消息處理機制。學習Android的消息處理機制,有幾個概念(類)必須了解:
1.?????? Message
消息,理解為線程間通訊的數據單元。例如后臺線程在處理數據完畢后需要更新UI,則可發送一條包含更新信息的Message給UI線程。
2.?????? Message Queue
消息隊列,用來存放通過Handler發布的消息,按照先進先出執行。
3.?????? Handler
Handler是Message的主要處理者,負責將Message添加到消息隊列以及對消息隊列中的Message進行處理。
4.?????? Looper
循環器,扮演Message Queue和Handler之間橋梁的角色,循環取出Message Queue里面的Message,并交付給相應的Handler進行處理。
?
5.??? 線程
UI thread 通常就是main thread,而Android啟動程序時會替它建立一個Message Queue。
每一個線程里可含有一個Looper對象以及一個MessageQueue數據結構。在你的應用程序里,可以定義Handler的子類別來接收Looper所送出的消息。
?
運行機理:
??????每個線程都可以并僅可以擁有一個Looper實例,消息隊列MessageQueue在Looper的構造函數中被創建并且作為成員變量被保存,也就是說MessageQueue相對于線程也是唯一的。Android應用在啟動的時候會默認會為主線程創建一個Looper實例,并借助相關的Handler和Looper里面的MessageQueue完成對Activities、Services、Broadcase Receivers等的管理。而在子線程中,Looper需要通過顯式調用Looper. Prepare()方法進行創建。Prepare方法通過ThreadLocal來保證Looper在線程內的唯一性,如果Looper在線程內已經被創建并且嘗試再度創建"Only one Looper may be created per thread"異常將被拋出。
?
??????Handler在創建的時候可以指定Looper,這樣通過Handler的sendMessage()方法發送出去的消息就會添加到指定Looper里面的MessageQueue里面去。在不指定Looper的情況下,Handler綁定的是創建它的線程的Looper。如果這個線程的Looper不存在,程序將拋出"Can't create handler inside thread that has not called Looper.prepare()"。
?
??????整個消息處理的大概流程是:1. 包裝Message對象(指定Handler、回調函數和攜帶數據等);2. 通過Handler的sendMessage()等類似方法將Message發送出去;3. 在Handler的處理方法里面將Message添加到Handler綁定的Looper的MessageQueue;4. Looper的loop()方法通過循環不斷從MessageQueue里面提取Message進行處理,并移除處理完畢的Message;5. 通過調用Message綁定的Handler對象的dispatchMessage()方法完成對消息的處理。
?
??????在dispatchMessage()方法里,如何處理Message則由用戶指定,三個判斷,優先級從高到低:1. Message里面的Callback,一個實現了Runnable接口的對象,其中run函數做處理工作;2. Handler里面mCallback指向的一個實現了Callback接口的對象,由其handleMessage進行處理;3. 處理消息Handler對象對應的類繼承并實現了其中handleMessage函數,通過這個實現的handleMessage函數處理消息。???
?
?
Android的消息機制(一)
?
android 有一種叫消息隊列的說法,這里我們可以這樣理解:假如一個隧道就是一個消息隊列,那么里面的每一部汽車就是一個一個消息,這里我們先忽略掉超車等種種因素,只那么先進隧道的車將會先出,這個機制跟我們android 的消息機制是一樣的。
一、????角色描述
1.Looper:(相當于隧道)一個線程可以產生一個Looper對象,由它來管理此線程里的Message Queue(車隊,消息隧道)。
2.Handler:你可以構造Handler對象來與Looper溝通,以便push新消息到Message Queue里;或者接收Looper(從Message Queue取出)所送來的消息。
3. Message Queue(消息隊列):用來存放線程放入的消息。
4.線程:UI thread通常就是main thread,而Android啟動程序時會替它建立一個Message Queue。
每一個線程里可含有一個Looper對象以及一個MessageQueue數據結構。在你的應用程序里,可以定義Handler的子類別來接收Looper所送出的消息。
?
在你的Android程序里,新誕生一個線程,或執行(Thread)時,并不會自動建立其Message Loop。
Android里并沒有Global的Message Queue數據結構,例如,不同APK里的對象不能透過Massage Queue來交換訊息(Message)。
例如:線程A的Handler對象可以傳遞消息給別的線程,讓別的線程B或C等能送消息來給線程A(存于A的Message Queue里)。
線程A的Message Queue里的訊息,只有線程A所屬的對象可以處理。
使用Looper.myLooper可以取得當前線程的Looper對象。
使用mHandler = new EevntHandler(Looper.myLooper());可用來構造當前線程的Handler對象;其中,EevntHandler是自已實現的Handler的子類別。
使用mHandler = new EevntHandler(Looper.getMainLooper());可誕生用來處理main線程的Handler對象;其中,EevntHandler是自已實現的Handler的子類別。
?
這樣描述可能太抽像,下面舉幾個實際的例子來說明:
二、????舉例
1.??同線程內不同組件間的消息傳遞
Looper類用來管理特定線程內對象之間的消息交換(Message Exchange)。你的應用程序可以產生許多個線程。而一個線程可以有許多個組件,這些組件之間常常需要互相交換訊息。如果有這種需要,您可以替線程構造一個Looper對象,來擔任訊息交換的管理工作。Looper對象會建立一個MessageQueue數據結構來存放各對象傳來的消息(包括UI事件或System事件等)。如下圖:
?
每一個線程里可含有一個Looper對象以及一個MessageQueue數據結構。在你的應用程序里,可以定義Handler的子類別來接收Looper所送出的消息。
同線程不同組件之間的消息傳遞:
publicclass?Activity1extends?Activityimplements?OnClickListener{
?????? Buttonbutton?=null;
?????? TextViewtext?=null;
??????@Override
??????protectedvoid?onCreate(Bundle savedInstanceState) {
?????????????super.onCreate(savedInstanceState);
????????????? setContentView(R.layout.activity1);????????
?????????????button?= (Button)findViewById(R.id.btn);
?????????????button.setOnClickListener(this);
?????????????text?= (TextView)findViewById(R.id.content);
?????? }
??????publicvoid?onClick(View v) {
?????????????switch?(v.getId()) {
?????????????case?R.id.btn:
???????????????????? Looper looper = Looper.myLooper();//取得當前線程里的looper
???????????????????? MyHandler mHandler =new?MyHandler(looper);//構造一個handler使之可與looper通信
????????????????????//buton等組件可以由mHandler將消息傳給looper后,再放入messageQueue中,同時mHandler也可以接受來自looper消息
???????????????????? mHandler.removeMessages(0);
???????????????????? String msgStr ="主線程不同組件通信:消息來自button";
???????????????????? Message m = mHandler.obtainMessage(1, 1, 1, msgStr);//構造要傳遞的消息
???????????????????? mHandler.sendMessage(m);//發送消息:系統會自動調用handleMessage方法來處理消息
????????????????????break;
?????????????? }????????????
?????? }?????
??????privateclass?MyHandlerextends?Handler{?????????????
?????????????public?MyHandler(Looper looper){
????????????????????super(looper);
????????????? }
?????????????@Override
?????????????publicvoid?handleMessage(Message msg) {//處理消息
????????????????????text.setText(msg.obj.toString());
????????????? }????????????
?????? }
}
?
說明:
此程序啟動時,當前線程(即主線程, main thread)已誕生了一個Looper對象,并且有了一個MessageQueue數據結構。
??? looper = Looper.myLooper ();?
調用Looper類別的靜態myLooper()函數,以取得目前線程里的Looper對象.
mHandler = new MyHandler (looper);
構造一個MyHandler對象來與Looper溝通。Activity等對象可以藉由MyHandler對象來將消息傳給Looper,然后放入MessageQueue里;MyHandler對象也扮演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!"于畫面上,
總結
以上是生活随笔為你收集整理的Dalvik/ART(ANDROID)中的多线程机制(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: layui官方文档
- 下一篇: jQuery插件——imgbox(点击图