如何使用Handler

来源:http://www.cnblogs.com/yishaochu/archive/2017/05/18/6875438.html
-Advertisement-
Play Games

什麼是Handler? Handler可以發送和處理消息對象或Runnable對象,這些消息對象和Runnable對象與一個線程相關聯。每個Handler的實例都關聯了一個線程和線程的消息隊列。當創建了一個Handler對象時,一個線程或消息隊列同時也被創建,該Handler對象將發送和處理這些消息 ...


什麼是Handler?

Handler可以發送和處理消息對象或Runnable對象,這些消息對象和Runnable對象與一個線程相關聯。每個Handler的實例都關聯了一個線程和線程的消息隊列。當創建了一個Handler對象時,一個線程或消息隊列同時也被創建,該Handler對象將發送和處理這些消息或Runnable對象。

handler類有兩種主要用途:

  • 執行Runnable對象,還可以設置延遲。
  • 兩個線程之間發送消息,主要用來給主線程發送消息更新UI。

為什麼要用Handler

解決多線程併發問題,假設如果在一個activity中,有多個線程去更新ui,並且都沒有加鎖機制,那界面顯示肯定會不正常。於是andoird官方就封裝了一套更新ui的機制,也可以用handler來實現多個線程之間的消息發送。

如何使用Handler

handler常用的方法有以下這些:

post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable,long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)

我們可以看到這些方法主要分為兩類,一種是傳入一個Runnable對象,一種是傳入一個Message對象。

用代碼來學習post一個Runnable對象

先創建Handler對象,直接new一個就行

private Handler handler=new Handler();

實現Runnable介面,用匿名實現方式,重寫run方法,就列印一個字元串。

private Runnable runnable=new Runnable() {
        @Override
        public void run() {
            Log.i("MainActivity","Handler Runnable");
        }
};

然後我們調用handler的post方法,這裡需要註意的是,post一個Runnable對象,底層用的是回調,不會開啟一個新的線程,所有Runnable的run方法還是在主線程裡面。是可以更新UI的。

handler.post(runnable);//執行
handler.postDelayed(runnable,2000);//延遲2秒後執行

運行程式,控制台列印的log如下:

05-18 19:17:14.901 17750-17750/com.ansen.handler I/MainActivity: Handler Runnable
05-18 19:17:16.901 17750-17750/com.ansen.handler I/MainActivity: Handler Runnable

從上面的log我們可以看到兩條Log的時間相差兩秒。這是因為我們用postDelayed方法的時候第二個參數設置了兩秒的延遲。

使用sendMessage方法傳遞消息

從方法的名字上我們可以理解用來發送消息,這個方法在android中使用頻率比較高,因為在Android中多線程中是不能更新UI的,必須要通過Handler把消息傳遞給UI線程,才能更新UI。當然也可以用Handler來兩個子線程發送消息。

我們給activity_main文件中TextView控制項設置一個id,然後在MainActivity中查找這個控制項,在多線程的for迴圈中給TextView賦值。增加後的代碼如下:

textview= (TextView) findViewById(R.id.textview);
new Thread(new Runnable(){
    @Override
    public void run(){
        for(int i=1;i<=100;i++){
            Log.i("MainActivity","當前值是:"+i);
            textview.setText("當前值是:"+i);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}).start();

重新運行代碼,程式奔潰。控制台列印如下log:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6024)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:820)

這是因為在android中不能在多線程中更新UI造成的。

每個應用啟動的時候,Android會啟動一個對應的主線程用來處理UI相關的事情,例如用戶的按鍵事件,用戶接觸屏幕的事件以及屏幕繪圖事件,並把相關的事件分發到對應的組件進行處理,所以主線程通常又被叫做UI線程。

這個時候我們就會用到Android的Handle類,Handle可以幫我們解決多線程不能更新UI問題,這裡我們只要知道使用這個類就行,在後面我們會詳細介紹它的原理。

接下來我們看如何用handler在主線程中接受子線程的消息,並且更新UI。首先new一個Handler的時候實現他的handleMessage方法,修改後的代碼如下:

private Handler handler=new Handler(){
    @Override
    public void handleMessage(Message msg) {
        if(msg.what==UPDATE_UI){
            textview.setText("當前值是:"+msg.obj);
        }
    }
};

我們可以看到把更新TextView的代碼放到這裡來了,並且用到handleMessage的msg參數。這個對象我們常用的一般就兩個屬性,what就是一個標示,我們發送消息的時候必需要指定值。obj:發送消息的參數。

再來看看多線程的run方法做了哪些改動,首先調用obtainMessage方法,這個方法呢是從消息池裡面返回一個Message對象,如果消息池沒有才會創建對象,這樣避免一直去new Message對象。message對象有what屬性是必需要賦值的,是一個int類型。前面我們講到過了,是一個標示。obj是發送消息用來傳參,這裡我們傳入的是i的值。最後調用handler.sendMessage(message)方法。然後我們handler的handleMessage方法就會回調。

new Thread(new Runnable(){
            @Override
            public void run(){
                for(int i=1;i<=100;i++){
                    Log.i("MainActivity","當前值是:"+i);
                    Message message=handler.obtainMessage();
                    message.what=UPDATE_UI;
                    message.obj=i;
                    handler.sendMessage(message);
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
}).start();

還有sendEmptyMessage跟sendMessageDelayed方法我就不一一給大家解釋了,有興趣的朋友自己去實現一下。

源碼下載

handler

如果你想第一時間看我們的後期文章,掃碼關註公眾號,每周不定期推送Android開發實戰教程文章,你還等什麼,趕快關註吧,學好技術,出任ceo,贏取白富美。。。。

      Android開發666 - 安卓開發技術分享
            掃描二維碼加關註

Android開發666


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

-Advertisement-
Play Games
更多相關文章
  • mouseover事件與mouseenter事件的區別 不論滑鼠指針穿過被選元素或其子元素,都會觸發 mouseover 事件。對應mouseout 只有在滑鼠指針穿過被選元素時,才會觸發 mouseenter 事件。對應mouseleave 我們來看看css代碼!!! 我們來看看HTML代碼!!! ...
  • (圖為微信首頁右上角『+』效果) 當初還在開發WP7的時候,從IOS同事那邊瞭解到類似微信以上功能的實現。 Item條數不同,總高度也不同,這就需要將背景圖片進行局部拉伸到響應的高度,並且保持上方的三角形不變型。 然而回想WP,沒找到有API能對圖片做此處理,只要圖片顯示比例與源圖比例不一樣,就會導 ...
  • 一,工程圖。 二,代碼。 三,輸出。 ...
  • 淺談Kotlin(一):簡介及Android Studio中配置 通過上面的文章,在Android Studio中我們已經可以進行Kotlin編程了,接下來開始學習Kotlin的基本類型及語法。 一、基本類型 在 Kotlin 中,所有變數的成員方法和屬性都是一個對象。 一些類型是內建的,它們的實現 ...
  • 使用block要註意迴圈引用,因此在塊中使用self前先使用__weak修飾生產弱引用 這裡記錄另一種情況:沒有使用屬性而是直接使用成員變數的時候 解決辦法 ...
  • 1.Drag拖拽;ViewDrag拖拽視圖,拖拽控制項;ViewDragHelper拖拽視圖助手,拖拽操作類。利用ViewDragHelper類可以實現很多絢麗的效果,比如:拖拽刪除,拖拽排序,側滑欄等。本篇主要講解簡易側滑欄的實現。 註意:ViewDragHelper是作用在一個ViewGroup上 ...
  • 在4.4之前狀態欄一直是黑色的,在4.4中帶來了 windowTranslucentStatus 這一特性,因此可以實現給狀態欄設置顏色,如下圖所示,狀態欄顏色不再是黑色,而是可以定製的顏色。 國內將狀態欄變色叫做沉浸式狀態欄,時間久了,叫的人多了,大家就不再深究,預設了這種叫法。 ...
  • 1.自定義VideoView 實現全屏播放 2.welcome_layout 3.WelcomeActivity 運行截圖: 運行截圖: ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...