handler

1. 瞭解幾個概念
1.Message 消息,理解爲線程間通訊的數據單元。例如後臺線程在處理數據完畢後需要更新UI,則可發送一條包含更新信息的Message給UI線程.
2.Message Queue 消息隊列,用來存放通過Handler發佈的消息,按照先進先出執行。
3.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所送出的消息。

2. 什麼是Handler
1. Handler 是 Android 給我們提供來更新 UI 的一套機制,也是一套消息處理的機制,我們可以發送消息,也可以通過它來處理消息,Handler 在我們的 framework 中是非常常見的。
2. Android 在設計的時候,就封裝了一套消息創建、傳遞、處理機制,如果不遵循這樣的機制就沒有辦法更新 UI 信息,就會拋出異常信息。



3. Handler 用法
1. 傳遞 Message
用於接受子線程發送的數據,並用此數據配合主線程更新 UI。有以下方法:
post(Ruannable);
postAtTime(Runnable, long);
postDelayed(Runnable long);
post類方法允許你排列一個 Runnable 對象到主線程隊列中。
2. 傳遞 Runnable 對象
用於通過 Handler 綁定的消息隊列,安排不同操作的執行順序,主要有以下方法:
sendEmptyMessage(int);
sendMessage(Message);
sendMessageAtTime(Message, long);
sendMessageDelayed(Message, long);
sendMessage 類方法,允許你安排一個帶數據的 Message 對象到隊列中,等待更新。
  1. 使用 Handler 在子線程中向 UI 線程發送一個消息進行 UI 的更新
  2. 創建一個 Message, Message msg = new Message(); msg.arg1 = 88;
  3. handler.sendMessage(msg); msg.obj = xxx; 可以傳遞一個對象
  4. 當然不一定要用 new 一個 Message,也可以複用系統的 message 對象 Message msg = handler.obtainMessage();
3. 傳遞 Callback 對象
Callback 用於截獲 handler 發送的消息,如果返回 true 就截獲成功不會向下傳遞了。
public Handler mHandler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        // TODO Auto-generated method stub
        Toast.makeText(getApplicationContext(), "HandleMessage 1", Toast.LENGTH_SHORT).show();
        return true;
    }
}) {
    public void handleMessage(Message msg) {
        // TODO Auto-generated method stub
        Toast.makeText(getApplicationContext(), "handleMessage 1", Toast.LENGTH_SHORT).show();
    };
}
上面的示例中,第一個有返回值的 handlerMessage 方法是 Callback 的回調,如果返回true,則不執行下面的 handlerMessage 方法,從而達到攔截 handler 發送的消息的目的,如果返回 false,則會繼續執行 handlerMessage 方法。

4. Handler 原理
4.1 Android 爲什麼要設計只能通過 Handler 機制更新 UI 呢?
最根本的目的就是解決多線程併發的問題,假設在一個 Activity 當中,有多個線程去更新 UI,並且對更新的 UI 的操作進行枷鎖處理的話又會產生什麼樣的問題呢? 那就是性能下降,Handler 通過消息隊列,保證了消息處理的先後有序。
鑑於以上問題的考慮,Android 給我們提供了一套更新 UI 的機制,我們只要使用一套機制就好,所有的更新 UI 的操作都是在主線程中輪詢處理。
4.2 Handler 的原理是什麼?
  1. Handler 封裝了消息的發送(主要包括消息發送給誰) Looper:
  • 內部包含一個消息隊列也就是 MessageQueue,所有 Handler 發送的消息都走向這個隊列。
  • Looper.loop()方法,就是一個 for 死循環,不斷的從 MessageQueue 取消息,如果有消息就處理消息,沒有消息就阻塞。
  1. MessageQueue,就是一個消息隊列,可以添加消息,處理消息。
  2. Handler 也不難,比較簡單,在構造 Handler 時候內部會跟 Looper 進行關聯,通過 Looper.myLooper() 獲取到 Looper,找到 Looper 也就找到了 MessageQueue。在 Handler 中發送消息,其實是向 MessageQueue 隊列中發送消息。
4.3 Handler 與 Looper、MessageQueue 的關係
這一小結:handler 負責發送消息,Looper 負責接收 Handler 發送消息,並直接把消息回傳給 handler 自己,MessageQueue 就是一個存儲消息的容器。
如上圖所示,一個線程中只有一個 Looper 實例,一個 MessageQueue 實例,可以有多個 Handler 實例。
下圖展示了 Handler、MessageQueue、Looper 之間是如何協作的。
下圖是一個“我要上廁所”的形象圖解:
5. Handler 與子線程
5.1 自定義與線程相關的 Handler
class MyThread extends Thread { public Handler handler; @Override public void run() { Looper.prepare(); //new 一個Looper對象 handler = new Handler() { //拿到當前線程的 Looper 對象 @Override public void handlerMessage(Message msg) { // TODO Auto-generated method stub System.out.println("current thread:" + Thread.currentThread()); } }; Looper.loop();//開始死循環處理消息 };}
一般 UI 主線程中不要執行一些耗時的操作,這樣就可以通過子線程消息來處理耗時操作。
5.2 HandlerThread是什麼?
HandlerThread 繼承於 Thread,所以它本質就是個 Thread。與普通的 Thread 的差別就在於,它有個 Looper 成員變量。這個 Looper 其實就是對消息隊列以及隊列處理邏輯的封裝,簡單來說就是消息隊列+消息循環。
當我們需要一個工作線程,而不是把它當作一次性消耗品,用過即廢的話,就可以使用它。
private Handler mHandler = null;
private HandlerThread mHandlerThread = null;
private void sendRunnableToWorker(Ruannable run) {  
if (null == mHandlerThread) {  
mHandlerThread = new HandlerThread("WorkerThread"); 
// 給工作者線程低優先級  
mHandlerThread.setPriority(Thread.MIN_PRIORITY);  
mHandlerThread.start();  
}  
if (null == mHandler) {  
mHandler = new Handler(mHandlerThread.getLooper());  
mHandler.post(run);
}
6. 主線程與子線程之間的信息交互
//創建主線程的Handler
private Handler mHandler = new Handler() { 
public void handleMessage(Message msg) {
Message mssage = new Message();  
System.out.println("main Handler");  
//向子線程發送消息  
threadHandler.sendMessageDelayed(message, 1000);  
};
};
//創建子線程的 handler
private Handler threadHandler;
@Override
protected void onCreate(Bundle saveInstanceState) { 
super.onCreate(savedInstanceState);  
setContentView(R.layout.main);  
HandlerThread thread = new HandlerThread("handlerThread"); 
//創建子線程的 handler  
threadHandler = new Handler(thread.getLooper()) {  
public void handlerMessage(Message msg) {  
Message message = new Message();  
//向主線程發送消息  
mHandler.sendMessageDelayed(message, 1000);  
};  
};
}
7. Android 中更新 UI 的幾種方式
Android 中更新 UI 的 4 種方式:
  1. runOnUiThread
  2. handler 的 post
  3. handler 的 sendMessage
  4. View 自身的 post

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