Handler的概念:
顧名思義,handler在英語中是“操作着,處理者的意思”,而官方的文檔給出的概念是,handler允許你發送或者處理Message對象或者Runable對象,這兩個對象都是與線程的Message queue相關聯的。每一個handler的實例(一個線程中可以有多個)都與單個的線程和那個線程對應的Messagequeue 關聯,而處理的先后則按照發送消息的先后,先進先出進行處理。
根據自己的理解,handler主要負責message的發送與消息的處理。
如下面例子 Handler handler=new Handler();//負責允許runable對象
Handler handler1 = new Handler()//負責接受message對象 { public void handleMessage(Message msg) { System.out.println("hanler1:run"+Thread.currentThread().getId()); } };
Runnable r=new Runnable(){ //這個runable對象,將在別的線程中執行 @Override public void run() { Message m = handler1.obtainMessage(); handler.post(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub System.out.println("handler2"+Thread.currentThread().getId()); }}); m.sendToTarget(); } };
Thread t=new Thread (r); //執行上面的runable t.start();
我們來先看看結果:
從上面結果來看,可以得出一點結論,那就是不管是Message還是runable對象,雖然是在別的線程通過handler發送消息,但是handler接到消息后,處理過程還是在handler所在的那個線程中(也就是本例中的主線程中)
在網上有些文章說,Message和runable是又兩個隊列來管理的,其實不是,我們不妨將
m.sendToTarget();移到
handler.post的前面
Runnable r=new Runnable(){ @Override public void run() { Message m = handler1.obtainMessage(); m.sendToTarget();//這個移到前面 handler.post(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub System.out.println("handler threadid="+Thread.currentThread().getId()); }}); } };
發現結果:
hanler1先執行了,說明,他們共用的一個隊列。
實際上Looper通過從Message queue從取出一個message,然后由優先級的從高到底判斷
message的類型,有三種類型( 1) Message里面的Callback,一個實現了Runnable接口的對象,其中run函數做處理工作;
2) Handler里面的mCallback指向的一個實現了Callback接口的對象,由其handleMessage進行處理;
3) 處理消息Handler對象對應的類繼承並實現了其中handleMessage函數,通過這個實現的handleMessage函數處理消息。)
Looper的概念
根據官方文檔的概念(Class used to run a message loop for a thread.)用來為線程處理消息循環
而線程中默認是沒有Looper的。為了給一個線程創建looper,執行Looper.prepar() 和Looper.loop()
實現如下
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } }
Looper在執行loop()里面處理消息
有人說為啥主線程里面沒有Looper.prepare() 和Looper.loop()呢,其實系統已經為主線程默認添加了這兩個方法,所以在主線程中,我們可以直接初始化handler。
而且如果你要自定義實現looper之后,必須在線程退出的時候,調用Looper.quit()。
下面再總結下:
每一個線程都可以包含一個Looper和一個消息隊列
在android中ui線程(也即主線程)默認有一個Looper和消息隊列
並且每一個Handler都有一個對應得message queue,而且一個線程中只有一個message queue,通過handler向message queue 發送消息,有兩種方式發送sendMessage,和post
兩者都可以更新UI線程。
經過測試,handler在哪個線程里面,不管是發送給他的message還是runale都在相對應的那個handler線程里面執行(一般是 主線程)
http://mobile.51cto.com/abased-375243.htm這篇文章上面說的有問題