Android: Handler 的用法詳解

Android 中 Handler 的用法詳解

Handler 是 Android 中用于線程間通信的重要機制,主要用于在不同線程之間發送和處理消息。以下是 Handler 的全面用法指南:

一、Handler 的基本原理

Handler 基于消息隊列(MessageQueue)和循環器(Looper)工作,主要組成:

  • Message:攜帶數據的消息對象
  • MessageQueue:消息隊列,存儲待處理的消息
  • Looper:消息循環,不斷從隊列取出消息處理
  • Handler:發送和處理消息的接口

二、基本用法

1. 創建 Handler(主線程)

// 在主線程創建Handler會自動關聯主線程的Looper
Handler mainHandler = new Handler(Looper.getMainLooper()) {@Overridepublic void handleMessage(Message msg) {// 處理消息switch (msg.what) {case 1:String text = (String) msg.obj;textView.setText(text);break;}}
};

2. 發送消息

// 發送空消息
handler.sendEmptyMessage(1);// 發送帶what的消息
Message msg = handler.obtainMessage();
msg.what = 2;
msg.obj = "Hello Handler";
handler.sendMessage(msg);// 延遲發送
handler.sendEmptyMessageDelayed(1, 1000); // 1秒后發送
handler.sendMessageDelayed(msg, 2000); // 2秒后發送

3. 在子線程使用 Handler

new Thread(() -> {// 為當前線程創建LooperLooper.prepare();Handler threadHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {// 處理子線程消息}};// 開始消息循環Looper.loop();
}).start();

三、Handler 的常見使用場景

1. 更新 UI

new Thread(() -> {// 模擬耗時操作try {Thread.sleep(1000);// 通過Handler發送消息到主線程更新UIMessage msg = mainHandler.obtainMessage();msg.what = 1;msg.obj = "更新后的文本";mainHandler.sendMessage(msg);} catch (InterruptedException e) {e.printStackTrace();}
}).start();

2. 定時任務

// 延遲執行
handler.postDelayed(() -> {Toast.makeText(this, "5秒后執行", Toast.LENGTH_SHORT).show();
}, 5000);// 循環執行
final Runnable runnable = new Runnable() {@Overridepublic void run() {// 執行任務Log.d("Handler", "每隔1秒執行");// 再次post實現循環handler.postDelayed(this, 1000);}
};
handler.postDelayed(runnable, 1000);// 取消定時任務
handler.removeCallbacks(runnable);

3. 線程間通信

// 工作線程
class WorkerThread extends Thread {public Handler workerHandler;@Overridepublic void run() {Looper.prepare();workerHandler = new Handler(Looper.myLooper()) {@Overridepublic void handleMessage(Message msg) {// 處理來自主線程的消息String task = (String) msg.obj;Log.d("WorkerThread", "執行任務: " + task);// 可以回傳結果給主線程Message resultMsg = mainHandler.obtainMessage();resultMsg.what = 2;resultMsg.obj = task + " 完成";mainHandler.sendMessage(resultMsg);}};Looper.loop();}
}// 主線程發送任務給工作線程
WorkerThread worker = new WorkerThread();
worker.start();// 等待workerHandler初始化
new Handler().postDelayed(() -> {if (worker.workerHandler != null) {Message msg = worker.workerHandler.obtainMessage();msg.obj = "下載文件";worker.workerHandler.sendMessage(msg);}
}, 1000);

四、高級用法

1. 使用 HandlerThread

// 創建HandlerThread
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();// 獲取HandlerThread的Looper創建Handler
Handler threadHandler = new Handler(handlerThread.getLooper()) {@Overridepublic void handleMessage(Message msg) {// 在后臺線程處理消息}
};// 發送消息
threadHandler.post(() -> {// 在HandlerThread中執行
});// 退出時釋放資源
handlerThread.quitSafely();

2. 避免內存泄漏

// 使用靜態內部類+弱引用
private static class SafeHandler extends Handler {private final WeakReference<Activity> activityRef;public SafeHandler(Activity activity) {super(Looper.getMainLooper());this.activityRef = new WeakReference<>(activity);}@Overridepublic void handleMessage(Message msg) {Activity activity = activityRef.get();if (activity != null && !activity.isFinishing()) {// 安全處理消息}}
}// 在Activity中使用
private SafeHandler safeHandler = new SafeHandler(this);

3. 使用 Message 的優化

// 復用Message對象(推薦)
Message msg = handler.obtainMessage(WHAT_ARG, obj);
handler.sendMessage(msg);// 設置回調代替繼承Handler
handler.sendMessage(Message.obtain(handler, () -> {// 回調處理
}));

五、注意事項

  1. 線程安全:Handler 與創建它的線程綁定,不能跨線程直接使用
  2. 內存泄漏:非靜態 Handler 內部類會持有外部類引用,Activity 銷毀時要移除回調
  3. Looper 準備:子線程使用 Handler 必須先調用 Looper.prepare()
  4. 消息堆積:避免發送過多消息導致消息隊列堵塞
  5. 及時清理:在 onDestroy() 中移除所有回調
@Override
protected void onDestroy() {super.onDestroy();handler.removeCallbacksAndMessages(null);if (handlerThread != null) {handlerThread.quitSafely();}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/899757.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/899757.shtml
英文地址,請注明出處:http://en.pswp.cn/news/899757.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

UE5學習筆記 FPS游戲制作33 游戲保存

文章目錄 核心思想創建數據對象創建UIUI參數和方法打開UI存檔文件的位置可以保存的數據類型 核心思想 UE自己有保存游戲的功能&#xff0c;核心節點&#xff0c;類似于json操作&#xff0c;需要一個數據類的對象來進行保存和讀取 創建存檔 加載存檔 保存存檔 創建數據對象…

【藍橋杯】 枚舉和模擬練習題

系列文章目錄 藍橋杯例題 枚舉和模擬 文章目錄 系列文章目錄前言一、好數&#xff1a; 題目參考&#xff1a;核心思想&#xff1a;代碼實現&#xff1a; 二、藝術與籃球&#xff1a; 題目參考&#xff1a;核心思想&#xff1a;代碼實現: 總結 前言 今天距離藍橋杯還有13天&…

大數據技術之Scala:特性、應用與生態系統

摘要 Scala 作為一門融合面向對象編程與函數式編程范式的編程語言&#xff0c;在大數據領域展現出獨特優勢。本文深入探討 Scala 的核心特性&#xff0c;如函數式編程特性、類型系統以及與 Java 的兼容性等。同時&#xff0c;闡述其在大數據處理框架&#xff08;如 Apache Spa…

Linux信號——信號的產生(1)

注&#xff1a;信號vs信號量&#xff1a;兩者沒有任何關系&#xff01; 信號是什么&#xff1f; Linux系統提供的&#xff0c;讓用戶&#xff08;進程&#xff09;給其他進程發送異步信息的一種方式。 進程看待信號的方式&#xff1a; 1.信號在沒有發生的時候&#xff0c;進…

數據結構和算法——漢諾塔問題

前言 先講個故事&#xff0c;傳說古代印度有三根黃金柱&#xff0c;64個石盤&#xff0c;需要將石盤從第一根移動到第三根上&#xff0c;規定每次只能移動一片&#xff0c;并且小盤在放置時必須在大盤上。 當石盤移動完畢時&#xff0c;世界就會毀滅。 漢諾塔——遞歸 接下來…

2023年3月全國計算機等級考試真題(二級C語言)

&#x1f600; 第1題 下列敘述中錯誤的是 A. 向量是線性結構 B. 非空線性結構中只有一個結點沒有前件 C. 非空線性結構中只有一個結點沒有后件 D. 只有一個根結點和一個葉子結點的結構必定是線性結構 概念澄清 首先&#xff0c;我們需要明確幾個關鍵概念&#xf…

Kafka簡單的性能調優

Kafka 的性能調優是一個系統性工程&#xff0c;需要從生產者、消費者、Broker 配置以及集群架構等多個層面進行綜合調整。以下是一些關鍵的性能調優策略&#xff1a; 一、生產者性能優化 批量發送 batch.size&#xff1a;控制消息批量的最大字節數&#xff0c;默認值為 16KB。…

微前端 - 以無界為例

一、微前端核心概念 微前端是一種將單體前端應用拆分為多個獨立子應用的架構模式&#xff0c;每個子應用可獨立開發、部署和運行&#xff0c;具備以下特點&#xff1a; 技術棧無關性&#xff1a;允許主應用和子應用使用不同框架&#xff08;如 React Vue&#xff09;。獨立部…

企業級日志分析平臺: ELK 集群搭建指南

前言&#xff1a;在當今數字化時代&#xff0c;數據已經成為企業決策的核心驅動力。無論是日志分析、用戶行為追蹤&#xff0c;還是實時監控和異常檢測&#xff0c;高效的數據處理和可視化能力都至關重要。ELK&#xff08;Elasticsearch、Logstash、Kibana&#xff09;作為全球…

1.2-WAF\CDN\OSS\反向代理\負載均衡

WAF&#xff1a;就是網站應用防火墻&#xff0c;有硬件類、軟件類、云WAF&#xff1b; 還有網站內置的WAF&#xff0c;內置的WAF就是直接嵌在代碼中的安全防護代碼 硬件類&#xff1a;Imperva、天清WAG 軟件&#xff1a;安全狗、D盾、云鎖 云&#xff1a;阿里云盾、騰訊云WA…

MybatisPlus(SpringBoot版)學習第四講:常用注解

目錄 1.TableName 1.1 問題 1.2 通過TableName解決問題 1.3 通過全局配置解決問題 2.TableId 2.1 問題 2.2 通過TableId解決問題 2.3 TableId的value屬性 2.4 TableId的type屬性 2.5 雪花算法 1.背景 2.數據庫分表 ①垂直分表 ②水平分表 1>主鍵自增 2>取…

第二屆計算機網絡和云計算國際會議(CNCC 2025)

重要信息 官網&#xff1a;www.iccncc.org 時間&#xff1a;2025年4月11-13日 地點&#xff1a;中國南昌 簡介 第二屆計算機網絡和云計算國際會議&#xff08;CNCC 2025&#xff09;將于2025年4月11-13日在中國南昌召開。圍繞“計算機網絡”與“云計算”展開研討&#xff…

【大模型基礎_毛玉仁】5.4 定位編輯法:ROME

目錄 5.4 定位編輯法&#xff1a;ROME5.4.1 知識存儲位置1&#xff09;因果跟蹤實驗2&#xff09;阻斷實驗 5.4.2 知識存儲機制5.4.3 精準知識編輯1&#xff09;確定鍵向量2&#xff09;優化值向量3&#xff09;插入知識 5.4 定位編輯法&#xff1a;ROME 定位編輯&#xff1a;…

橫掃SQL面試——連續性登錄問題

橫掃SQL面試 &#x1f4cc; 連續性登錄問題 在互聯網公司的SQL面試中&#xff0c;連續性問題堪稱“必考之王”。&#x1f4bb;&#x1f50d; 用戶連續登錄7天送優惠券&#x1f31f;&#xff0c;服務器連續報警3次觸發熔斷??&#xff0c;圖書館連續3天人流破百開啟限流?” …

Spring AI Alibaba 對話記憶使用

一、對話記憶 (ChatMemory)簡介 1、對話記憶介紹 ”大模型的對話記憶”這一概念&#xff0c;根植于人工智能與自然語言處理領域&#xff0c;特別是針對具有深度學習能力的大型語言模型而言&#xff0c;它指的是模型在與用戶進行交互式對話過程中&#xff0c;能夠追蹤、理解并利…

vdi模式是什么

?VDI模式&#xff08;Virtual Desktop Infrastructure&#xff09;是一種基于服務器的計算模型&#xff0c;其核心思想是將所有計算和存儲資源集中在服務器上&#xff0c;用戶通過前端設備&#xff08;如瘦客戶機&#xff09;訪問服務器上的虛擬桌面?? VDI模式的工作原理 在…

【分布式】深入剖析 Sentinel 限流:原理、實現

在當今分布式系統盛行的時代&#xff0c;流量的劇增給系統穩定性帶來了巨大挑戰。Sentinel 作為一款強大的流量控制組件&#xff0c;在保障系統平穩運行方面發揮著關鍵作用。本文將深入探討 Sentinel 限流的原理、實現方案以及其優缺點&#xff0c;助力開發者更好地運用這一工具…

c#winform,倒鴨子字幕效果,typemonkey字幕效果,抖音瀑布流字幕效果

不廢話 直接上效果圖 C# winform 開發抖音的瀑布流字幕。 也是typemonkey插件字幕效果 或者咱再網上常說的倒鴨子字幕效果 主要功能 1&#xff0c;軟件可以自定義添加字幕內容 2&#xff0c;軟件可以添加字幕顯示的時間區間 3&#xff0c;可以自定義字幕顏色&#xff0c;可以隨…

Pycharm(八):字符串切片

一、字符串分片介紹 對操作的對象截取其中一部分的操作&#xff0c;比如想要獲取字符串“888666qq.com前面的qq號的時候就可以用切片。 字符串、列表、元組都支持切片操作。 語法&#xff1a;字符串變量名 [起始:結束:步長] 口訣&#xff1a;切片其實很簡單&#xff0c;只顧頭來…

圖片解釋git的底層工作原理

&#xff08;圖片來源&#xff1a;自己畫的&#xff09; 基于同一個commit創建新分支 &#xff08;圖片來源&#xff1a;書籍《Linux運維之道》 ISBN 9787121461811&#xff09; 在新分支上修改然后commit一次 &#xff08;圖片來源&#xff1a;書籍《Linux運維之道》 ISBN 978…