handler looper 和 線程


 

 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這篇文章上面說的有問題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM