![](http://upload-images.jianshu.io/upload_images/944365-207a738cb165a2da.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
前言
在
Android
开发的多线程应用场景中,Handler
机制十分常用今天,我将献上一份
Handler
机制的使用教程 ,希望你们会喜欢
阅读本文前,请先阅读:Android Handler:图文解析 Handler通信机制 的工作原理
目录
![](http://upload-images.jianshu.io/upload_images/944365-b3bf342725cfa4a5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
1. Handler 机制简介
定义
一套Android
消息传递机制 / 异步通信机制作用
在多线程的应用场景中,将工作线程中需更新UI
的操作信息 传递到 UI
主线程,从而实现 工作线程对UI
的更新处理,最终实现异步消息的处理
![](http://upload-images.jianshu.io/upload_images/944365-4a64038632c4c88f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/656)
- 为什么要用
Handler
消息传递机制
答:多个线程并发更新UI的同时 保证线程安全。具体描述如下
![](http://upload-images.jianshu.io/upload_images/944365-7479b4a8b8fe48bf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
- 总结
使用Handler
的原因:将工作线程需操作UI
的消息 传递 到主线程,使得主线程可根据工作线程的需求 更新UI
,从而避免线程操作不安全的问题
2. 相关概念
关于 Handler
机制中的相关概念如下:
在下面的讲解中,我将直接使用英文名讲解,即
Handler
、Message
、Message Queue
、Looper
,希望大家先熟悉相关概念
![](http://upload-images.jianshu.io/upload_images/944365-d08903087cb575d9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
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
<?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
下来再看,效果会更好哦!)
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();
}
}
- 运行结果
![](http://upload-images.jianshu.io/upload_images/944365-c7418cfe17b16f11.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/388)
方式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();
}
}
- 运行结果
![](http://upload-images.jianshu.io/upload_images/944365-c7418cfe17b16f11.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/388)
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
的异步消息传递机制的使用讲解完毕。
6. 总结
- 本文对
Handler
异步通信传递机制的使用进行了全面讲解 - 下面我将继续深入讲解
Android
中的Handler
异步通信传递机制的相关知识,如 工作机制流程、源码解析等,有兴趣可以继续关注Carson_Ho的安卓开发笔记
请点赞!因为你的鼓励是我写作的最大动力!
相关文章阅读
Android开发:最全面、最易懂的Android屏幕适配解决方案
Android事件分发机制详解:史上最全面、最易懂
Android开发:史上最全的Android消息推送解决方案
Android开发:最全面、最易懂的Webview详解
Android开发:JSON简介及最全面解析方法!
Android四大组件:Service服务史上最全面解析
Android四大组件:BroadcastReceiver史上最全面解析
欢迎关注Carson_Ho的简书!
不定期分享关于安卓开发的干货,追求短、平、快,但却不缺深度。
![](http://upload-images.jianshu.io/upload_images/944365-9b76fa3c52d478a7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
作者:Carson_Ho
链接:https://www.jianshu.com/p/e172a2d58905
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。