前言
在
Android
开发的多线程应用场景中,Handler
机制十分常用今天,我将献上一份
Handler
机制的使用教程 ,希望你们会喜欢
阅读本文前,请先阅读:Android多线程一:Android中的消息机制Handler
目录
1. Handler 机制简介
定义
一套Android
消息传递机制 / 异步通信机制作用
在多线程的应用场景中,将工作线程中需更新UI
的操作信息 传递到 UI
主线程,从而实现 工作线程对UI
的更新处理,最终实现异步消息的处理
- 为什么要用
Handler
消息传递机制
答:多个线程并发更新UI的同时 保证线程安全。具体描述如下
- 总结
使用Handler
的原因:将工作线程需操作UI
的消息 传递 到主线程,使得主线程可根据工作线程的需求 更新UI
,从而避免线程操作不安全的问题
2. 相关概念
关于 Handler
机制中的相关概念如下:
在下面的讲解中,我将直接使用英文名讲解,即
Handler
、Message
、Message Queue
、Looper
,希望大家先熟悉相关概念
3. 使用方式
-
Handler
使用方式 因发送消息到消息队列的方式不同而不同 - 共分为2种:使用
Handler.sendMessage()
、使用Handler.post()
4. 使用步骤
方式1:使用 Handler.sendMessage()
在该使用方式中,又分为2种:新建Handler
子类(内部类)、匿名 Handler
子类
但本质相同,即 继承了
Handler
类 & 创建了子类
/**
* 方式1:新建Handler子类(内部类)
*/
// 步骤1:自定义Handler子类(继承Handler类) & 复写handleMessage()方法
class mHandler extends Handler {
// 通过复写handlerMessage() 从而确定更新UI的操作
@Override
public void handleMessage(Message msg) {
...// 需执行的UI操作
}
}
// 步骤2:在主线程中创建Handler实例
private Handler mhandler = new mHandler();
// 步骤3:创建所需的消息对象
Message msg = Message.obtain(); // 实例化消息对象
msg.what = 1; // 消息标识
msg.obj = "AA"; // 消息内容存放
// 步骤4:在工作线程中 通过Handler发送消息到消息队列中
// 可通过sendMessage() / post()
// 多线程可采用AsyncTask、继承Thread类、实现Runnable
mHandler.sendMessage(msg);
// 步骤5:开启工作线程(同时启动了Handler)
// 多线程可采用AsyncTask、继承Thread类、实现Runnable
/**
* 方式2:匿名内部类
*/
// 步骤1:在主线程中 通过匿名内部类 创建Handler类对象
private Handler mhandler = new Handler(){
// 通过复写handlerMessage()从而确定更新UI的操作
@Override
public void handleMessage(Message msg) {
...// 需执行的UI操作
}
};
// 步骤2:创建消息对象
Message msg = Message.obtain(); // 实例化消息对象
msg.what = 1; // 消息标识
msg.obj = "AA"; // 消息内容存放
// 步骤3:在工作线程中 通过Handler发送消息到消息队列中
// 多线程可采用AsyncTask、继承Thread类、实现Runnable
mHandler.sendMessage(msg);
// 步骤4:开启工作线程(同时启动了Handler)
// 多线程可采用AsyncTask、继承Thread类、实现Runnable
方式2:使用Handler.post()
// 步骤1:在主线程中创建Handler实例
private Handler mhandler = new mHandler();
// 步骤2:在工作线程中 发送消息到消息队列中 & 指定操作UI内容
// 需传入1个Runnable对象
mHandler.post(new Runnable() {
@Override
public void run() {
... // 需执行的UI操作
}
});
// 步骤3:开启工作线程(同时启动了Handler)
// 多线程可采用AsyncTask、继承Thread类、实现Runnable
5. 实例讲解
本文将用实例逐个讲解 Handler
的用法
注:
- 由于
Handler
的作用 = 将工作线程需操作UI的消息 传递 到主线程,使得主线程可根据工作线程的需求 更新UI,从而避免线程操作不安全的问题- 故下文的实例 = 1个简单 “更新
UI
操作” 的案例- 主布局文件相同 = 1个用于展示的
TextView
,具体如下:
布局代码:activity_main.xml
实例的源码地址:Carson_Ho的Github:Handler
(建议:先fork
下来再看,效果会更好哦!)
5.1 使用 Handler.sendMessage()
方式1:新建Handler子类(内部类)
- 具体使用
public class MainActivity extends AppCompatActivity {
public TextView mTextView;
public Handler mHandler;
// 步骤1:(自定义)新创建Handler子类(继承Handler类) & 复写handleMessage()方法
class Mhandler extends Handler {
// 通过复写handlerMessage() 从而确定更新UI的操作
@Override
public void handleMessage(Message msg) {
// 根据不同线程发送过来的消息,执行不同的UI操作
// 根据 Message对象的what属性 标识不同的消息
switch (msg.what) {
case 1:
mTextView.setText("执行了线程1的UI操作");
break;
case 2:
mTextView.setText("执行了线程2的UI操作");
break;
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.show);
// 步骤2:在主线程中创建Handler实例
mHandler = new Mhandler();
// 采用继承Thread类实现多线程演示
new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 步骤3:创建所需的消息对象
Message msg = Message.obtain();
msg.what = 1; // 消息标识
msg.obj = "A"; // 消息内存存放
// 步骤4:在工作线程中 通过Handler发送消息到消息队列中
mHandler.sendMessage(msg);
}
}.start();
// 步骤5:开启工作线程(同时启动了Handler)
// 此处用2个工作线程展示
new Thread() {
@Override
public void run() {
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 通过sendMessage()发送
// a. 定义要发送的消息
Message msg = Message.obtain();
msg.what = 2; //消息的标识
msg.obj = "B"; // 消息的存放
// b. 通过Handler发送消息到其绑定的消息队列
mHandler.sendMessage(msg);
}
}.start();
}
}
- 运行结果
方式2:匿名内部类
- 具体使用
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:在主线程中 通过匿名内部类 创建Handler类对象
mHandler = new Handler(){
// 通过复写handlerMessage()从而确定更新UI的操作
@Override
public void handleMessage(Message msg) {
// 根据不同线程发送过来的消息,执行不同的UI操作
switch (msg.what) {
case 1:
mTextView.setText("执行了线程1的UI操作");
break;
case 2:
mTextView.setText("执行了线程2的UI操作");
break;
}
}
};
// 采用继承Thread类实现多线程演示
new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 步骤3:创建所需的消息对象
Message msg = Message.obtain();
msg.what = 1; // 消息标识
msg.obj = "A"; // 消息内存存放
// 步骤4:在工作线程中 通过Handler发送消息到消息队列中
mHandler.sendMessage(msg);
}
}.start();
// 步骤5:开启工作线程(同时启动了Handler)
// 此处用2个工作线程展示
new Thread() {
@Override
public void run() {
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 通过sendMessage()发送
// a. 定义要发送的消息
Message msg = Message.obtain();
msg.what = 2; //消息的标识
msg.obj = "B"; // 消息的存放
// b. 通过Handler发送消息到其绑定的消息队列
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:在主线程中创建Handler实例
mHandler = new Handler();
// 步骤2:在工作线程中 发送消息到消息队列中 & 指定操作UI内容
new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 通过psot()发送,需传入1个Runnable对象
mHandler.post(new Runnable() {
@Override
public void run() {
// 指定操作UI内容
mTextView.setText("执行了线程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("执行了线程2的UI操作");
}
});
}
}.start();
}
}
-
运行结果
至此,关于Handler
的异步消息传递机制的使用讲解完毕。
作者:Carson_Ho
链接:https://www.jianshu.com/p/e172a2d58905