Handler消息傳遞機制

来源:http://www.cnblogs.com/haoxiaozhang/archive/2016/03/08/5251268.html
-Advertisement-
Play Games

出於性能優化考慮,Android的UI操作並不是線程安全的,這意味著如果有多個線程併發操作UI組件,可能導致線程安全問題。為瞭解決這個問題,Android制定了一條簡單的規則:只允許UI線程修改Activity里的UI組件。 當一個程式第一次啟動時,Android會同時啟動一條主線程(Main Th


       出於性能優化考慮,Android的UI操作並不是線程安全的,這意味著如果有多個線程併發操作UI組件,可能導致線程安全問題。為瞭解決這個問題,Android制定了一條簡單的規則:只允許UI線程修改Activity里的UI組件。

       當一個程式第一次啟動時,Android會同時啟動一條主線程(Main Thread),主線程主要負責處理與UI相關的事件,如用戶的按鍵事件、用戶接觸屏幕的事件及屏幕繪圖事件,並把相關的事件分發到對應的組件進行處理。所以主線程通常又被叫做UI線程。

       Android的消息傳遞機制是另一種形式的“事件處理”,這種機制主要是為瞭解決Android應用的多線程問題——Android平臺只允許UI線程修改Activity里的UI組件,這樣就會導致新啟動的線程無法動態改變界面組件的屬性值。但在實際Android應用開發中,尤其是涉及動畫的游戲開發中,需要讓新啟動的線程周期性地改變界面組件的屬性值,這就需要藉助於Handler的消息傳遞機制來實現了。

Handler類簡介

   Handler類的主要作用有兩個:

     1、在新啟動的線程中發送消息。

     2、在主線程中獲取、處理消息。

   為了讓主線程能“適時”地處理新啟動的線程所發送的消息,顯然只能通過回調的方式來實現——開發者只要重寫 Handler 類中處理消息的方法,當新啟動的線程發送消息時,消息會發送到與之關聯的 MessageQueue ,而 Handler 會不斷地從MessageQueue 中獲取並處理消息——這將導致 Handler 類中處理消息的方法被回調。

Handler類包含如下方法用於發送、處理消息。

  1、void handleMessage(Message msg):處理消息的方法。該方法通常用於被重寫。

  2、final boolean hasMessages(int what):檢查消息隊列中是否包含what屬性為指定值得消息。

  3、final boolean hsaMessages(int what,Object object):檢查消息隊列中是否包含what屬性為指定值且object屬性為指定對象的消息。

  4、多個重載的 Message obtainMessage():獲取消息。

  5、sendEmptyMessage(int what):發送空消息。

  6、final boolean sendEmptyMessageDelayed(int what,long delayMills):指定多少毫秒之後發送空消息。

  7、final boolean sendMessage(Message msg):立即發送消息。

  8、final boolean sendMessageDelayed(Message msg,long delayMillis):指定多少毫秒之後發送消息。

藉助於上面這些方法,程式可以方便地利用Handler 類進行消息傳遞。

Handler、Loop、MessageQueue的工作原理

  為了更好的理解Handler的工作原理,先介紹一下與Handler一起工作的幾個組件。

  1、Message:Handler 接受和處理的消息對象

  2、Looper:每個線程只能擁有一個Looper。它的loop方法負責讀取MessageQueue中的消息,讀到消息之後就把消息交給發送消息的Handler進行處理。

  3、MessageQueue:消息隊列,它採用先進先出的方法來管理Message。程式創建Looper對象時會在它的構造器中創建Looper對象。Looper 提供的構造器源代碼如下:

1 private Looper()
2 {
3   mQueue=new MessageQueue();
4   mRun=true;
5   mThread=Thread.currentThread();
6 }

   該構造器使用了 private 修飾,表明程式員無法通過構造器創建Looper對象。從上面的代碼中不難看出,程式在初始化Looper時會創建一個與之關聯的 MessageQueue ,這個MessageQueue就負責管理消息。

  1、Handler:它的作用有兩個——發送消息和處理消息,程式使用Handler發送消息,被Handler發送的消息必須被送到指定的MessageQueue。也就是說,如果希望Handler正常工作,必須在當前線程中有一個MessageQueue,否則消息就沒有MessageQueue進行保存了。不過MessageQueue是由Looper負責管理的,也就是說,如果希望Handler正常工作,必須在當前線程中有一個Looper對象,為了保證當前線程中有Looper對象,可以分如下兩種情況處理。

  1、主UI線程中,系統已經初始化了一個Looper對象,因此程式直接創建Handler即可,然後就可通過Handler來發送消息、處理消息。

  2、程式員自己啟動的子線程,程式員必須自己創建一個Looper對象,並啟動它。創建Looper對象調用它的prepare()方法即可。

prepare()方法保證每個線程最多只有一個Looper對象。prepare()方法的源代碼如下:

public static final void prepare()
{
    if(sThreadLocal.get()!=null)
    {
        throw new RuntimeException("Only one Looper may be createed per thread");
    }
    sThreadLocal.set(new Looper());
}

   然後調用Looper 的靜態 loop() 方法來啟動它。loop()方法使用一個死迴圈不斷取出MessageQueue 中的消息,並將取出的消息分給對應的Handler進行處理。

 

  歸納起來,Looper、MessageQueue、Handler 各自的作用如下:

  1、Looper:每個線程只有一個Looper,它負責管理 MessageQueue ,會不斷地從MessageQueue中取出消息。並將消息分給對應的Handler處理。

  2、MessageQueue:由Looper負責管理。它採用先進先出的方法來管理Message。

  3、Handler:它能把消息發送給Looper管理的MessageQueue,並負責處理Looper分給它的消息。

 線上程中使用Handler的步驟如下:

     1、調用Looper的prepare()方法為當前線程創建Looper對象,創建Looper對象時,它的構造器會創建與之配套的MessageQueue。

  2、有了Looper之後,創建Handler子類的實例,重寫handlerMessage()方法,該方法負責處理來自於其他線程的消息。

  3、調用Looper的loop()方法啟動Looper。

 


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

-Advertisement-
Play Games
更多相關文章
  • 當Activity 處於Android 應用中運行時,它的活動狀態由 Android 以 Activity 棧的形式管理。當前活動的Activity位於棧頂。隨著不同應用的運行,每個Activity都有可能從活動狀態轉入非活動狀態,也可能從非活動狀態轉入活動狀態。 Activity 的生命周期 歸納
  • 所謂的單例就是:一個應用程式(app)只有一個實例化對象,這個對象就是單例,一般用於音樂播放器和工具類 在這裡教大家如何手動創建單例,一種是利用互斥鎖的方式,另一種是利用dispatch的一次性執行. 1//通過互斥鎖創建單例 2 +(instancetype)sharedNetWorkTools
  • 概述 我們平時也使用了很多的xcode插件,雖然官方對於插件製作沒有提供任何支持,但是載入三方的插件,預設還是被允許的.第三方的插件,需要存放在 ~/Library/Application Support/Developer/Shared/Xcode/Plug-ins文件夾中,尾碼名必須是.xcpl
  • 用eclipse新建Android工程時,自動生成的appcompat_v7出錯,有個紅色交叉,而且新建的Android工程有一個紅色感嘆號。 這時你去看看你新建的Android工程是不是沒有生成R文件。當你Refresh和Clean都毫無成效後,不妨更新sdk試試。 更新sdk的時候只需要安裝SD
  • Android的UI線程主要負責處理用戶的按鍵事件、用戶觸屏事件及屏幕繪圖事件等,因此開發者的其他操作不應該、也不能阻塞UI線程,否則UI界面將會變得停止響應——用戶感覺非常糟糕。(總之,開發者需要牢記:不要再UI線程中執行一些耗時的操作)。 為了避免UI線程失去響應的問題,Android建議將耗時
  • 在iOS系統,使用Url Scheme框架在APP間互相跳轉和傳遞數據,本文只介紹如果檢測和跳轉。 Url Scheme框架 如果你想知道ios設備中是否安裝QQ這個軟體,我們可以通過一個簡單方法判斷到 if ([[UIApplication sharedApplication] canOpenUR
  • 代碼示例:https://github.com/johnlui/Swift-On-iOS/tree/master/ControlOrientation/ControlOrientation 環境要求:Xcode 7 / Swift2.0 前兩天遇到了一個 “使用指定的不同屏幕方向打開新頁面” 的需求
  • 上篇介紹了RoboGuice的接入及基本使用,其中涉及到了一個@Singleton和@ContextSingleton的註解,這些都是作用域的註解,這篇我們先說明有關作用域的問題。 一.作用域 Scope Scope指的是作用域,指的就是註入的對象的生命周期,RoboGuice提供了預設的幾個作用域
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...