Android Handler消息傳遞機制

来源:http://www.cnblogs.com/upwgh/archive/2016/09/23/5901124.html
-Advertisement-
Play Games

handler通俗一點講就是用來在各個線程之間發送數據的處理對象。在任何線程中,只要獲得了另一個線程的handler,則可以通過 handler.sendMessage(message)方法向那個線程發送數據。基於這個機制,我們在處理多線程的時候可以新建一個thread,這個thread擁有UI線程... ...


1. Handler消息傳遞機制初步認識:什麼是Handler?
handler通俗一點講就是用來在各個線程之間發送數據的處理對象。在任何線程中,只要獲得了另一個線程的handler,則可以通過 handler.sendMessage(message)方法向那個線程發送數據。基於這個機制,我們在處理多線程的時候可以新建一個thread,這個thread擁有UI線程中的一個handler。當thread處理完一些耗時的操作後通過傳遞過來的handler向UI線程發送數據,由UI線程去更新界面。
主線程:運行所有UI組件,它通過一個消息隊列來完成此任務。設備會將用戶 的每項操作轉換為消息,並將它們放入正在運行的消息隊列中。主線程位於一個迴圈中,並處理每條消息。如果任何一個消息用時超過5秒,Android將拋出 ANR。所以一個任務用時超過5秒,應該在一個獨立線程中完成它,或者延遲處理它,當主線程空閑下來再返回來處理它。

2.常用類:(Handler、Looper、Message、MessageQueue)
Message:消息,其中包含了消息ID,消息處理對象以及處理的數據等,由MessageQueue統一列隊,終由Handler處理。
Handler:處理者,負責Message的發送及處理。使用Handler時,需要實現 handleMessage(Message msg)方法來對特定的Message進行處理,例如更新UI等。Handler類的主要作用:(有兩個主要作用)1)、在工作線程中發送消息;2)、在 主線程中獲w/取、並處理消息。
MessageQueue:消息隊列,用來存放Handler發送過來的消息,並按照FIFO規則執行。當然,存放Message並非實際意義的保存,而是將Message串聯起來的,等待Looper的抽取。
Looper:消息泵,不斷地從MessageQueue中抽取Message執行。因此,一個MessageQueue需要一個Looper。

3.Handler、Looper、Message、MessageQueue之間的關係:

  • Looper和MessageQueue一一對應,創建一個Looper的同時,會創建一個MessageQueue;
  • 而Handler與它們的關係,只是簡單的聚集關係,即Handler里會引用當前線程里的特定Looper和MessageQueue;
  • 在一個線程中,只能有一個Looper和MessageQueue,但是可以有多個Handler,而且這些Handler可以共用一個Looper和MessageQueue;
  • Message被存放在 MessageQueue中,一個 MessageQueue中可以包含多個Message對象

【備註:】
Looper對象用來為一個線程開啟一個消息迴圈,從而操作MessageQueue;
預設情況下,Android創建的線程沒有開啟消息迴圈Looper,但是主線程例外。
系統自動為主線程創建Looper對象,開啟消息迴圈;
所以主線程中使用new來創建Handler對象。而子線程中不能直接new來創建Handler對象就會異常。
子線程中創建Handler對象,步驟如下:
Looper.prepare();
Handler handler = new Handler() {
//handlemessage(){}
}
Looper.loop();

4.Handler類中常用方法:
(1) handleMessage() 用在主線程中,構造Handler對象時,重寫handleMessage()方法。該方法根據工作線程返回的消息標識,來分別執行不同的操作。
(2) sendEmptyMessage() 用在工作線程中,發送空消息。
(3) sendMessage() 用在工作線程中,立即發送消息。

5.Message消息類中常用屬性:
(1) arg1 用來存放整型數據
(2) arg2 用來存放整型數據
(3) obj 用來存放Object數據
(4) what 用於指定用戶自定義的消息代碼,這樣便於主線程接收後,根據消息代碼不同而執行不同的相應操作。

上一下Demo的示例代碼:

private Handler handler = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text_main_info = (TextView) findViewById(R.id.text_main_info);
        pDialog = new ProgressDialog(MainActivity.this);
        pDialog.setMessage("Loading...");
        image_main = (ImageView) findViewById(R.id.image_main);

        // 主線程中的handler對象會處理工作線程中發送的Message。根據Message的不同編號進行相應的操作。
        handler = new Handler() {
                public void handleMessage(android.os.Message msg) {
                        // 工作線程中要發送的信息全都被放到了Message對象中,也就是上面的參數msg中。要進行操作就要先取出msg中傳遞的數據。
                        switch (msg.what) {
                        case 0:
                                // 工作線程發送what為0的信息代表線程開啟了。主線程中相應的顯示一個進度對話框
                                pDialog.show();
                                break;
                        case 1:
                                // 工作線程發送what為1的信息代表要線程已經將需要的數據載入完畢。本案例中就需要將該數據獲取到,顯示到指定ImageView控制項中即可。
                                image_main.setImageBitmap((Bitmap) msg.obj);
                                break;
                        case 2:
                                // 工作線程發送what為2的信息代表工作線程結束。本案例中,主線程只需要將進度對話框取消即可。
                                pDialog.dismiss();
                                break;
                        }
                }
        };

        new Thread(new Runnable() {
                @Override
                public void run() {
                        // 當工作線程剛開始啟動時,希望顯示進度對話框,此時讓handler發送一個空信息即可。
                        // 當發送這個信息後,主線程會回調handler對象中的handleMessage()方法。handleMessage()方法中
                        // 會根據message的what種類來執行不同的操作。
                        handler.sendEmptyMessage(0);

                        // 工作線程執行訪問網路,載入網路圖片的任務。
                        byte[] data = HttpClientHelper.loadByteFromURL(urlString);
                        // 工作線程將網路訪問獲取的位元組數組生成Bitmap點陣圖。
                        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,
                                        data.length);
                        // 工作線程將要發送給主線程的信息都放到一個Message信息對象中。
                        // 而Message對象的構建建議使用obtain()方法生成,而不建議用new來生成。
                        Message msgMessage = Message.obtain();
                        // 將需要傳遞到主線程的數據放到Message對象的obj屬性中,以便於傳遞到主線程。
                        msgMessage.obj = bitmap;
                        // Message對象的what屬性是為了區別信息種類,而方便主線程中根據這些類別做相應的操作。
                        msgMessage.what = 1;
                        // handler對象攜帶著Message中的數據返回到主線程
                        handler.sendMessage(msgMessage);

                        // handler再發出一個空信息,目的是告訴主線程工作線程的任務執行完畢。一般主線程會接收到這個消息後,
                        // 將進度對話框關閉
                        handler.sendEmptyMessage(2);
                }
        }).start();
}

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • xUtils簡介 xUtils 包含了很多實用的android工具。 xUtils 最初源於Afinal框架,進行了大量重構,使得xUtils支持大文件上傳,更全面的http請求協議支持(10種謂詞),擁有更加靈活的ORM,更多的事件註解支持且不受混淆影響... xUitls最低相容android ...
  • 一、 準備階段 二、程式編寫 支付介面需要幾個必要的參數 partnerID 為開發者申請的使用者ID,以2088開頭;sellerId 為收款賬戶(一般為申請的開發賬號,即圖片中的登錄賬號,也可使用其他支付寶賬號);privatekey 私鑰用於訂單信息處理。 開發者可在這個頁面獲取到這些信息,如 ...
  • 先看效果圖: 1、Action:該activity可以執行的動作 該標識用來說明這個activity可以執行哪些動作,所以當隱式intent傳遞過來action時,如果跟這裡<intent-filter>所列出的任意一個匹配的話,就說明這個activity是可以完成這個intent的意圖的,可以將它 ...
  • 在《Android 手機衛士--解析json與消息機制發送不同類型消息》一文中,消息機制發送不同類型的信息還沒有完全實現,在出現異常的時候,應該彈出吐司提示異常,代碼如下: 因為彈出吐司操作比較常見,於是將其寫成工具類進行簡單的封裝,方便以後調用。 本文地址:http://www.cnblogs.c ...
  • 說明:實現功能:(1)屏幕右半部分上滑,聲音變大,下滑,聲音變小 屏幕左半部分上滑,亮度變大,下滑,亮度變小(2)如果亮度>1或者小於0.2時,手機震動 private float startY;//記錄手指按下時的Y坐標 private float startX;//記錄手指按下時的Y坐標 pri ...
  • 本文地址:http://www.cnblogs.com/wuyudong/p/5900800.html,轉載請註明源地址。 1、解析json數據 解析json的代碼很簡單 2、使用消息機制發送不同類型消息 在獲取伺服器端json數據後,得到app的版本號,通過和客戶端的版本號進行對比 可以使用and ...
  • 文本轉語音技術, 也叫TTS, 是Text To Speech的縮寫. iOS如果想做有聲書等功能的時候, 會用到這門技術. 一,使用iOS自帶TTS需要註意的幾點: 二,代碼示例, 播放語音 三,AVSpeechSynthesizer介紹 這個類就像一個會說話的人, 可以”說話”, 可以”暫停”說 ...
  • 添加配置許可權 添加Push Notifications支持 開關開啟後會自動生成xxxx.entitlements文件 這裡需要註意幾點 生成的該文件是否包含到你的打包工程中Bundle Resources中 如果沒有手動添加進去 如果工程有多個Target 且多個證書在一起建議不要使用 Autom ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...