Android Handler實現原理

下面介紹最本質的多線程:hanlder和message機制:

爲何需要多線程:

在日常應用中,我們通常需要處理一些“後臺,用戶不可見”的操作,例如說,我們需要下載一個音樂,要是你的應用必須等用戶下載完成之後纔可以進行別的操作,那肯定讓用戶非常的不爽。這時候,我們通常的做法是,讓這些操作去後臺執行,然後等後臺執行完畢之後,再給用戶彈出相應的提示信息。這時候,我們就需要使用多線程機制,然後通過創建一個新的線程來執行這些操作。

明白了,實現需求,我們就準備着手實現了。但是,經過進一步的瞭解,我們悲劇的發現,android中的線程機制是,只能在UI線程中和用戶進行交互。當我們創建了一個新線程,執行了一些後臺操作,執行完成之後,我們想要給用戶彈出對話框以確認,但是卻悲劇的發現,我們根本無法返回UI主線程了。

(說明:何爲UI線程:UI線程就是你當前看到的這些交互界面所屬的線程)。

這時候,我們如果想要實現這些功能,我們就需要一個android爲我們提供的handler和message機制。

先講解下編程機制:

我們通常在UI線程中創建一個handler,handler相當於一個處理器,它主要負責處理和綁定到該handler的線程中的message。每一個handler都必須關聯一個looper,並且兩者是一一對應的,注意,這點很重要哦!此外,looper負責從其內部的messageQueue中拿出一個個的message給handler進行處理。因爲我們這裏handler是在UI線程中實現的,所以經過這麼一個handler、message機制,我們就可以回到UI線程中了。

何爲handler:處理後臺進程返回數據的工作人員。

何爲message:後臺進程返回的數據,裏面可以存儲bundle等數據格式

何爲messageQueue:是線程對應looper的一部分,負責存儲從後臺進程中拋回的和當前handler綁定的message,是一個隊列。

何爲looper:looper相當於一個messageQueue的管理人員,它會不停的循環的遍歷隊列,然後將符合條件的message一個個的拿出來交給handler進行處理。

注意,handler是在UI線程中聲明的,如果我們直接用類似代碼執行一個線程的話,實際上並沒有創建一個新的線程,因爲handler已經跟默認的UI線程中的looper綁定了。

如果有興趣的話,可以去看下Handler的默認空構造函數便知道原因了,裏面直接綁定了當前UI線程的looper。

下面給出一個比較簡單,並且實用的實例。

源碼打印?
package cn.com.src;  
   
import cn.com.chenzheng_java.utils.R;  
import android.app.Activity;  
import android.os.Bundle;  
import android.os.Handler;  
import android.os.HandlerThread;  
import android.os.Looper;  
import android.os.Message;  
import android.util.Log;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.widget.Button;  
   
 
public class HanlderMessageTest extends Activity implements OnClickListener{  
 Button button ;  
 MyHandler handler ;  
   
 @Override  
 protected void onCreate(Bundle savedInstanceState) {  
 super.onCreate(savedInstanceState);  
 setContentView(R.layout.main);  
 button = (Button) this.findViewById(R.id.button1);  
 button.setOnClickListener(this);  
   
   
   
 }  
   
 // 聲明自己的handler  
 private class MyHandler extends Handler{  
   
 public MyHandler() {  
 super();  
 }  
   
 public MyHandler(Looper looper){  
 super(looper);  
 }  
   
 // 處理具體的message,該方法由父類中進行繼承.  
 @Override  
 public void handleMessage(Message msg) {  
 int whatNumber = msg.what;  
 Bundle bundle = (Bundle)msg.obj;  
 Log.i("what", whatNumber+"");  
 Log.i("名稱", bundle.getString("name"));  
 Log.i("性別", bundle.getString("sex"));  
 Log.i("年齡", bundle.getString("age"));  
 super.handleMessage(msg);  
 }  
 }  
  
 // 我自定義的任務,一般都會實現Runnable  
 private class MyThread implements Runnable {  
   
 @Override  
 public void run() {  
   
 try {  
 Thread.sleep(6000);  
 Message message = Message.obtain(handler);  
 message.what = 10 ;  
 Bundle bundle = new Bundle();  
 bundle.putString("name", "chenzheng");  
 bundle.putString("sex", "純爺們");  
 bundle.putString("age", "生卒年不詳");  
 message.obj = bundle ;  
 Log.i("通知", "開始發message了哦");  
 Log.i("通知thread_id:", ""+Thread.currentThread().getId());  
 message.sendToTarget();  
 } catch (Exception e) {  
 Log.i("通知", "線程sleep時出錯了!");  
 e.printStackTrace();  
 }  
 }  
 }  
   
 @Override  
 public void onClick(View v) {  
 Log.i("通知thread_id:", ""+Thread.currentThread().getId());  
   
 // 創建一個包含Looper的線程,這裏如果沒有HandlerThread的調用,會直接將後邊的MyThread放到UI線程隊列  
 HandlerThread myHandlerThread = new HandlerThread("chenzheng_java");  
 // 啓動新線程  
 myHandlerThread.start();  
 // 將handler綁定到新線程  
 handler = new MyHandler(myHandlerThread.getLooper());  
 // 在新線程中執行任務   
 handler.post(new MyThread());  
 }  
}  


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章