Android Handler 的用法指南
Android 中 Handler 的用法詳解
Handler 是 Android 中用于線程間通信的重要機制,主要用于在不同線程之間發(fā)送和處理消息。以下是 Handler 的全面用法指南:
一、Handler 的基本原理
Handler 基于消息隊列(MessageQueue)和循環(huán)器(Looper)工作,主要組成:
- Message:攜帶數(shù)據(jù)的消息對象
- MessageQueue:消息隊列,存儲待處理的消息
- Looper:消息循環(huán),不斷從隊列取出消息處理
- Handler:發(fā)送和處理消息的接口
二、基本用法
1. 創(chuàng)建 Handler(主線程)
// 在主線程創(chuàng)建Handler會自動關(guān)聯(lián)主線程的Looper
Handler mainHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
// 處理消息
switch (msg.what) {
case 1:
String text = (String) msg.obj;
textView.setText(text);
break;
}
}
};2. 發(fā)送消息
// 發(fā)送空消息 handler.sendEmptyMessage(1); // 發(fā)送帶what的消息 Message msg = handler.obtainMessage(); msg.what = 2; msg.obj = "Hello Handler"; handler.sendMessage(msg); // 延遲發(fā)送 handler.sendEmptyMessageDelayed(1, 1000); // 1秒后發(fā)送 handler.sendMessageDelayed(msg, 2000); // 2秒后發(fā)送
3. 在子線程使用 Handler
new Thread(() -> {
// 為當前線程創(chuàng)建Looper
Looper.prepare();
Handler threadHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 處理子線程消息
}
};
// 開始消息循環(huán)
Looper.loop();
}).start();三、Handler 的常見使用場景
1. 更新 UI
new Thread(() -> {
// 模擬耗時操作
try {
Thread.sleep(1000);
// 通過Handler發(fā)送消息到主線程更新UI
Message msg = mainHandler.obtainMessage();
msg.what = 1;
msg.obj = "更新后的文本";
mainHandler.sendMessage(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();2. 定時任務
// 延遲執(zhí)行
handler.postDelayed(() -> {
Toast.makeText(this, "5秒后執(zhí)行", Toast.LENGTH_SHORT).show();
}, 5000);
// 循環(huán)執(zhí)行
final Runnable runnable = new Runnable() {
@Override
public void run() {
// 執(zhí)行任務
Log.d("Handler", "每隔1秒執(zhí)行");
// 再次post實現(xiàn)循環(huán)
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(runnable, 1000);
// 取消定時任務
handler.removeCallbacks(runnable);3. 線程間通信
// 工作線程
class WorkerThread extends Thread {
public Handler workerHandler;
@Override
public void run() {
Looper.prepare();
workerHandler = new Handler(Looper.myLooper()) {
@Override
public void handleMessage(Message msg) {
// 處理來自主線程的消息
String task = (String) msg.obj;
Log.d("WorkerThread", "執(zhí)行任務: " + task);
// 可以回傳結(jié)果給主線程
Message resultMsg = mainHandler.obtainMessage();
resultMsg.what = 2;
resultMsg.obj = task + " 完成";
mainHandler.sendMessage(resultMsg);
}
};
Looper.loop();
}
}
// 主線程發(fā)送任務給工作線程
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
// 創(chuàng)建HandlerThread
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
// 獲取HandlerThread的Looper創(chuàng)建Handler
Handler threadHandler = new Handler(handlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
// 在后臺線程處理消息
}
};
// 發(fā)送消息
threadHandler.post(() -> {
// 在HandlerThread中執(zhí)行
});
// 退出時釋放資源
handlerThread.quitSafely();2. 避免內(nèi)存泄漏
// 使用靜態(tài)內(nèi)部類+弱引用
private static class SafeHandler extends Handler {
private final WeakReference<Activity> activityRef;
public SafeHandler(Activity activity) {
super(Looper.getMainLooper());
this.activityRef = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
Activity activity = activityRef.get();
if (activity != null && !activity.isFinishing()) {
// 安全處理消息
}
}
}
// 在Activity中使用
private SafeHandler safeHandler = new SafeHandler(this);3. 使用 Message 的優(yōu)化
// 復用Message對象(推薦)
Message msg = handler.obtainMessage(WHAT_ARG, obj);
handler.sendMessage(msg);
// 設置回調(diào)代替繼承Handler
handler.sendMessage(Message.obtain(handler, () -> {
// 回調(diào)處理
}));五、注意事項
- 線程安全:Handler 與創(chuàng)建它的線程綁定,不能跨線程直接使用
- 內(nèi)存泄漏:非靜態(tài) Handler 內(nèi)部類會持有外部類引用,Activity 銷毀時要移除回調(diào)
- Looper 準備:子線程使用 Handler 必須先調(diào)用 Looper.prepare()
- 消息堆積:避免發(fā)送過多消息導致消息隊列堵塞
- 及時清理:在 onDestroy() 中移除所有回調(diào)
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacksAndMessages(null);
if (handlerThread != null) {
handlerThread.quitSafely();
}
}到此這篇關(guān)于Android Handler 的用法詳解的文章就介紹到這了,更多相關(guān)Android Handler 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Android Handler的使用詳解
- Android Handler使用案例詳解
- 深入Android HandlerThread 使用及其源碼完全解析
- Android使用Handler實現(xiàn)打地鼠游戲
- Android使用Handler實現(xiàn)倒計時功能
- Android使用Handler實現(xiàn)定時器與倒計時器功能
- Android開發(fā)使用Handler的PostDelayed方法實現(xiàn)圖片輪播功能
- Android 異步任務 設置 超時使用handler更新通知功能
- Android HandlerThread的使用及原理詳解
- Android使用Handler和Message更新UI
- Android開發(fā)使用UncaughtExceptionHandler捕獲全局異常
相關(guān)文章
Android實現(xiàn)擴大View點擊區(qū)域的三種方式
在 Android 應用開發(fā)中,有時候需要擴大 View 的點擊區(qū)域以提高用戶交互的便利性,尤其是當視圖元素較小或用戶界面密集時,以下提供幾種擴大點擊區(qū)域的思路,感興趣的小伙伴跟著小編一起來看看吧2024-08-08
Android使用SQLiteDatabase增刪改查(CRUD)的操作教程
在 Android 中使用 SQLiteDatabase 進行增刪改查操作是開發(fā)中的核心技能之一,下面我將詳細說明如何使用 SQLiteDatabase 進行 CRUD 操作,需要的朋友可以參考下2025-04-04
在Visual Studio上構(gòu)建C++的GUI框架wxWidgets的開發(fā)環(huán)境
這篇文章主要介紹了Visual Studio上構(gòu)件C++的GUI框架wxWidgets開發(fā)環(huán)境的方法,wxWidgets是一個跨多個系統(tǒng)平臺的圖形化界面開發(fā)框架,并且可用語言不限于C++,需要的朋友可以參考下2016-04-04
zxing二維碼位矩陣轉(zhuǎn)換成Bitmap位圖的實戰(zhàn)教程
二維碼的應用已經(jīng)可以說是非常廣泛了,下面這篇文章主要給大家介紹了關(guān)于zxing二維碼位矩陣轉(zhuǎn)換成Bitmap位圖的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-09-09
Android圖像視圖ImageView實現(xiàn)圖像拉伸效果
這篇文章主要為大家詳細介紹了Android圖像視圖ImageView實現(xiàn)圖像拉伸演示,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-05-05
Android 開發(fā)使用PopupWindow實現(xiàn)加載等待界面功能示例
這篇文章主要介紹了Android 開發(fā)使用PopupWindow實現(xiàn)加載等待界面功能,結(jié)合實例形式分析了Android使用PopupWindow組件實現(xiàn)加載等待界面功能相關(guān)布局與功能實現(xiàn)技巧,需要的朋友可以參考下2020-05-05
淺析Android位置權(quán)限以及數(shù)組尋找索引的坑
這篇文章給大家分享了Android位置權(quán)限以及數(shù)組尋找索引的坑的相關(guān)知識點內(nèi)容,有興趣的朋友可以參考學習下。2018-07-07
Android頭像上傳功能的實現(xiàn)代碼(獲取頭像加剪切)
最近在做一個頭像上傳的項目,下面小編給大家分享Android頭像上傳功能的實現(xiàn)代碼,需要的的朋友參考下吧2017-08-08

