
前言
在Android開發(fā)的多線程應用場景中,Handler機制十分常用。今天,我將獻上一份 Handler機制的使用教程 ,希望你們會喜歡
Anroid異步通信Handler系列文章
Android異步通信:Handler機制學習攻略
Android異步通信:Handler使用教程
Android異步通信:Handler工作原理
Android異步通信:Handler源碼分析
Android異步通信:詳解Handler內(nèi)存泄露的原因
目錄

1. Handler 機制簡介
定義
一套Android消息傳遞機制 / 異步通信機制作用
在多線程的應用場景中,將工作線程中需更新UI的操作信息 傳遞到 UI主線程,從而實現(xiàn) 工作線程對UI的更新處理,最終實現(xiàn)異步消息的處理

- 為什么要用
Handler消息傳遞機制
答:多個線程并發(fā)更新UI的同時 保證線程安全。具體描述如下

- 總結
使用Handler的原因:將工作線程需操作UI的消息 傳遞 到主線程,使得主線程可根據(jù)工作線程的需求 更新UI,從而避免線程操作不安全的問題
2. 相關概念
關于 Handler 機制中的相關概念如下:
在下面的講解中,我將直接使用英文名講解,即
Handler、Message、Message Queue、Looper,希望大家先熟悉相關概念

3. 使用方式
-
Handler使用方式 因發(fā)送消息到消息隊列的方式不同而不同 - 共分為2種:使用
Handler.sendMessage()、使用Handler.post()
4. 使用步驟
方式1:使用 Handler.sendMessage()
在該使用方式中,又分為2種:新建Handler子類(內(nèi)部類)、匿名 Handler子類
但本質(zhì)相同,即 繼承了
Handler類 & 創(chuàng)建了子類
/**
* 方式1:新建Handler子類(內(nèi)部類)
*/
// 步驟1:自定義Handler子類(繼承Handler類) & 復寫handleMessage()方法
class mHandler extends Handler {
// 通過復寫handlerMessage() 從而確定更新UI的操作
@Override
public void handleMessage(Message msg) {
...// 需執(zhí)行的UI操作
}
}
// 步驟2:在主線程中創(chuàng)建Handler實例
private Handler mhandler = new mHandler();
// 步驟3:創(chuàng)建所需的消息對象
Message msg = Message.obtain(); // 實例化消息對象
msg.what = 1; // 消息標識
msg.obj = "AA"; // 消息內(nèi)容存放
// 步驟4:在工作線程中 通過Handler發(fā)送消息到消息隊列中
// 可通過sendMessage() / post()
// 多線程可采用AsyncTask、繼承Thread類、實現(xiàn)Runnable
mHandler.sendMessage(msg);
// 步驟5:開啟工作線程(同時啟動了Handler)
// 多線程可采用AsyncTask、繼承Thread類、實現(xiàn)Runnable
/**
* 方式2:匿名內(nèi)部類
*/
// 步驟1:在主線程中 通過匿名內(nèi)部類 創(chuàng)建Handler類對象
private Handler mhandler = new Handler(){
// 通過復寫handlerMessage()從而確定更新UI的操作
@Override
public void handleMessage(Message msg) {
...// 需執(zhí)行的UI操作
}
};
// 步驟2:創(chuàng)建消息對象
Message msg = Message.obtain(); // 實例化消息對象
msg.what = 1; // 消息標識
msg.obj = "AA"; // 消息內(nèi)容存放
// 步驟3:在工作線程中 通過Handler發(fā)送消息到消息隊列中
// 多線程可采用AsyncTask、繼承Thread類、實現(xiàn)Runnable
mHandler.sendMessage(msg);
// 步驟4:開啟工作線程(同時啟動了Handler)
// 多線程可采用AsyncTask、繼承Thread類、實現(xiàn)Runnable
方式2:使用Handler.post()
// 步驟1:在主線程中創(chuàng)建Handler實例
private Handler mhandler = new mHandler();
// 步驟2:在工作線程中 發(fā)送消息到消息隊列中 & 指定操作UI內(nèi)容
// 需傳入1個Runnable對象
mHandler.post(new Runnable() {
@Override
public void run() {
... // 需執(zhí)行的UI操作
}
});
// 步驟3:開啟工作線程(同時啟動了Handler)
// 多線程可采用AsyncTask、繼承Thread類、實現(xiàn)Runnable
5. 實例講解
本文將用實例逐個講解 Handler的用法
注:
- 由于
Handler的作用 = 將工作線程需操作UI的消息 傳遞 到主線程,使得主線程可根據(jù)工作線程的需求 更新UI,從而避免線程操作不安全的問題- 故下文的實例 = 1個簡單 “更新
UI操作” 的案例- 主布局文件相同 = 1個用于展示的
TextView,具體如下:
布局代碼:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context="com.example.carson_ho.handler_learning.MainActivity">
<TextView
android:id="@+id/show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" />
</RelativeLayout>
實例的源碼地址:Carson_Ho的Github:Handler
(建議:先fork下來再看,效果會更好哦?。?/p>
5.1 使用 Handler.sendMessage()
方式1:新建Handler子類(內(nèi)部類)
- 具體使用
public class MainActivity extends AppCompatActivity {
public TextView mTextView;
public Handler mHandler;
// 步驟1:(自定義)新創(chuàng)建Handler子類(繼承Handler類) & 復寫handleMessage()方法
class Mhandler extends Handler {
// 通過復寫handlerMessage() 從而確定更新UI的操作
@Override
public void handleMessage(Message msg) {
// 根據(jù)不同線程發(fā)送過來的消息,執(zhí)行不同的UI操作
// 根據(jù) Message對象的what屬性 標識不同的消息
switch (msg.what) {
case 1:
mTextView.setText("執(zhí)行了線程1的UI操作");
break;
case 2:
mTextView.setText("執(zhí)行了線程2的UI操作");
break;
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.show);
// 步驟2:在主線程中創(chuàng)建Handler實例
mHandler = new Mhandler();
// 采用繼承Thread類實現(xiàn)多線程演示
new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 步驟3:創(chuàng)建所需的消息對象
Message msg = Message.obtain();
msg.what = 1; // 消息標識
msg.obj = "A"; // 消息內(nèi)存存放
// 步驟4:在工作線程中 通過Handler發(fā)送消息到消息隊列中
mHandler.sendMessage(msg);
}
}.start();
// 步驟5:開啟工作線程(同時啟動了Handler)
// 此處用2個工作線程展示
new Thread() {
@Override
public void run() {
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 通過sendMessage()發(fā)送
// a. 定義要發(fā)送的消息
Message msg = Message.obtain();
msg.what = 2; //消息的標識
msg.obj = "B"; // 消息的存放
// b. 通過Handler發(fā)送消息到其綁定的消息隊列
mHandler.sendMessage(msg);
}
}.start();
}
}
- 運行結果

方式2:匿名內(nèi)部類
- 具體使用
public class MainActivity extends AppCompatActivity {
public TextView mTextView;
public Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.show);
// 步驟1:在主線程中 通過匿名內(nèi)部類 創(chuàng)建Handler類對象
mHandler = new Handler(){
// 通過復寫handlerMessage()從而確定更新UI的操作
@Override
public void handleMessage(Message msg) {
// 根據(jù)不同線程發(fā)送過來的消息,執(zhí)行不同的UI操作
switch (msg.what) {
case 1:
mTextView.setText("執(zhí)行了線程1的UI操作");
break;
case 2:
mTextView.setText("執(zhí)行了線程2的UI操作");
break;
}
}
};
// 采用繼承Thread類實現(xiàn)多線程演示
new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 步驟3:創(chuàng)建所需的消息對象
Message msg = Message.obtain();
msg.what = 1; // 消息標識
msg.obj = "A"; // 消息內(nèi)存存放
// 步驟4:在工作線程中 通過Handler發(fā)送消息到消息隊列中
mHandler.sendMessage(msg);
}
}.start();
// 步驟5:開啟工作線程(同時啟動了Handler)
// 此處用2個工作線程展示
new Thread() {
@Override
public void run() {
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 通過sendMessage()發(fā)送
// a. 定義要發(fā)送的消息
Message msg = Message.obtain();
msg.what = 2; //消息的標識
msg.obj = "B"; // 消息的存放
// b. 通過Handler發(fā)送消息到其綁定的消息隊列
mHandler.sendMessage(msg);
}
}.start();
}
}
- 運行結果

5.2 使用 Handler.post()
- 具體使用
public class MainActivity extends AppCompatActivity {
public TextView mTextView;
public Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.show);
// 步驟1:在主線程中創(chuàng)建Handler實例
mHandler = new Handler();
// 步驟2:在工作線程中 發(fā)送消息到消息隊列中 & 指定操作UI內(nèi)容
new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 通過psot()發(fā)送,需傳入1個Runnable對象
mHandler.post(new Runnable() {
@Override
public void run() {
// 指定操作UI內(nèi)容
mTextView.setText("執(zhí)行了線程1的UI操作");
}
});
}
}.start();
// 步驟3:開啟工作線程(同時啟動了Handler)
// 此處用2個工作線程展示
new Thread() {
@Override
public void run() {
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mHandler.post(new Runnable() {
@Override
public void run() {
mTextView.setText("執(zhí)行了線程2的UI操作");
}
});
}
}.start();
}
}
-
運行結果
示意圖
至此,關于Handler的異步消息傳遞機制的使用講解完畢。
6. 總結
- 本文對
Handler異步通信傳遞機制的使用進行了全面講解 - 下一篇文章我將對講解
Android Handler的相關知識,感興趣的同學可以繼續(xù)關注Carson_Ho的簡書
Anroid異步通信Handler系列文章
Android異步通信:Handler機制學習攻略
Android異步通信:Handler使用教程
Android異步通信:Handler工作原理
Android異步通信:Handler源碼分析
Android異步通信:詳解Handler內(nèi)存泄露的原因
歡迎關注Carson_Ho的簡書
不定期分享關于安卓開發(fā)的干貨,追求短、平、快,但卻不缺深度。

