Handler机制
目录结构
1. 了解几个概念
很多Android初学者对Android 中的Handler不是很明白,其实Google参考了Windows的消息处理机制,在Android系统中实现了一套类似的消息处理机制。
在下面介绍Handler机制前,首先得了解以下几个概念:
Message
消息,理解为线程间通讯的数据单元。例如后台线程在处理数据完毕后需要更新UI,则可发送一条包含更新信息的Message给UI线程。Message Queue
消息队列,用来存放通过Handler发布的消息,按照先进先出执行。Handler
Handler是Message的主要处理者,负责将Message添加到消息队列以及对消息队列中的Message进行处理。Looper
循环器,扮演Message Queue和Handler之间桥梁的角色,循环取出Message Queue里面的Message,并交付给相应的Handler进行处理。线程
UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。每一个线程里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类别来接收Looper所送出的消息。
2. 什么是Handler
- Handler 是 Android 给我们提供来更新 UI 的一套机制,也是一套消息处理的机制,我们可以发送消息,也可以通过它来处理消息,Handler 在我们的 framework 中是非常常见的。
- Android 在设计的时候,就封装了一套消息创建、传递、处理机制,如果不遵循这样的机制就没有办法更新 UI 信息,就会抛出异常信息。
3. Handler用法
3.1 传递message
用于接受子线程发送的数据,并用此数据配合主线程更新 UI。有以下方法:
post(Ruannable);
postAtTime(Runnable, long);
postDelayed(Runnable long);
post类方法允许你排列一个 Runnable 对象到主线程队列中。
3.2 传递Runnable对象
用于通过 Handler 绑定的消息队列,安排不同操作的执行顺序,主要有以下方法:
sendEmptyMessage(int);
sendMessage(Message);
sendMessageAtTime(Message, long);
sendMessageDelayed(Message, long);
sendMessage 类方法,允许你安排一个带数据的 Message 对象到队列中,等待更新。
- 使用 Handler 在子线程中向 UI 线程发送一个消息进行 UI 的更新
- 创建一个 Message,
Message msg = new Message(); msg.arg1 = 88;
handler.sendMessage(msg); msg.obj = xxx;
可以传递一个对象- 当然不一定要用 new 一个 Message,也可以复用系统的 message 对象
Message msg = handler.obtainMessage();
3.3 传递Callback对象
Callback 用于截获 handler 发送的消息,如果返回 true 就截获成功不会向下传递了。
public Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "HandleMessage 1", Toast.LENGTH_SHORT).show();
return true;
}
}) {
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "handleMessage 1", Toast.LENGTH_SHORT).show();
};
}
上面的示例中,第一个有返回值的 handlerMessage 方法是 Callback 的回调,如果返回true,则不执行下面的 handlerMessage 方法,从而达到拦截 handler 发送的消息的目的,如果返回 false,则会继续执行 handlerMessage 方法。
4. Handler原理
4.1 Android为什么设计成只能通过Handler机制更新UI呢?
最根本的目的就是解决多线程并发的问题,假设在一个 Activity 当中,有多个线程去更新 UI,并且对更新的 UI 的操作进行枷锁处理的话又会产生什么样的问题呢? 那就是性能下降,Handler 通过消息队列,保证了消息处理的先后有序。
鉴于以上问题的考虑,Android 给我们提供了一套更新 UI 的机制,我们只要使用一套机制就好,所有的更新 UI 的操作都是在主线程中轮询处理。
4.2 Handler的原理是什么?
- Handler 封装了消息的发送(主要包括消息发送给谁) Looper:
- 内部包含一个消息队列也就是 MessageQueue,所有 Handler 发送的消息都走向这个队列。
- Looper.loop()方法,就是一个 for 死循环,不断的从 MessageQueue 取消息,如果有消息就处理消息,没有消息就阻塞。
- MessageQueue,就是一个消息队列,可以添加消息,处理消息。
- Handler 也不难,比较简单,在构造 Handler 时候内部会跟 Looper 进行关联,通过 Looper.myLooper() 获取到 Looper,找到 Looper 也就找到了 MessageQueue。在 Handler 中发送消息,其实是向 MessageQueue 队列中发送消息。
4.3 handler与Looper、MessageQueue的关系?
这一小结:handler 负责发送消息,Looper 负责接收 Handler 发送消息,并直接把消息回传给 handler 自己,MessageQueue 就是一个存储消息的容器。
如上图所示,一个线程中只有一个 Looper 实例,一个 MessageQueue 实例,可以有多个 Handler 实例。
下图展示了 Handler、MessageQueue、Looper 之间是如何协作的。
下图是一个“我要上厕所”的形象图解:
5. Handler与子线程
5.1 自定义与线程相关的Handler
class MyThread extends Thread {
public Handler handler;
@Override
public void run() {
Looper.prepare(); //new 一个Looper对象
handler = new Handler() { //拿到当前线程的 Looper 对象
@Override
public void handlerMessage(Message msg) {
// TODO Auto-generated method stub
System.out.println("current thread:" + Thread.currentThread());
}
};
Looper.loop();//开始死循环处理消息
};
}
一般 UI 主线程中不要执行一些耗时的操作,这样就可以通过子线程消息来处理耗时操作。
5.2 HandlerThread是什么?
HandlerThread 继承于 Thread,所以它本质就是个 Thread。与普通的 Thread 的差别就在于,它有个 Looper 成员变量。这个 Looper 其实就是对消息队列以及队列处理逻辑的封装,简单来说就是消息队列+消息循环。
当我们需要一个工作线程,而不是把它当作一次性消耗品,用过即废的话,就可以使用它。
private Handler mHandler = null;
private HandlerThread mHandlerThread = null;
private void sendRunnableToWorker(Ruannable run) {
if (null == mHandlerThread) {
mHandlerThread = new HandlerThread("WorkerThread");
// 给工作者线程低优先级
mHandlerThread.setPriority(Thread.MIN_PRIORITY);
mHandlerThread.start();
}
if (null == mHandler) {
mHandler = new Handler(mHandlerThread.getLooper());
}
mHandler.post(run);
}
6. 主线程与子线程之间的信息交互
//创建主线程的Handler
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
Message mssage = new Message();
System.out.println("main Handler");
//向子线程发送消息
threadHandler.sendMessageDelayed(message, 1000);
};
};
//创建子线程的 handler
private Handler threadHandler;
@Override
protected void onCreate(Bundle saveInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
HandlerThread thread = new HandlerThread("handlerThread");
//创建子线程的 handler
threadHandler = new Handler(thread.getLooper()) {
public void handlerMessage(Message msg) {
Message message = new Message();
//向主线程发送消息
mHandler.sendMessageDelayed(message, 1000);
};
};
}
7. Android中更新UI的几种方式
Android 中更新 UI 的 4 种方式:
- runOnUiThread
- handler 的 post
- handler 的 sendMessage
- View 自身的 post
Handler机制的更多相关文章
- Android的Handler机制
Handler机制的原理 Android 的 Handler 机制(也有人叫消息机制)目的是为了跨线程通信,也就是多线程通信.之所以需 要跨线程通信是因为在 Android 中主线程通常只负责 UI ...
- Android中的Handler机制
直接在UI线程中开启子线程来更新TextView显示的内容,运行程序我们会发现,如下错 误:android.view.ViewRoot$CalledFromWrongThreadException: ...
- 安卓Handler机制的例子
Handler机制是实现线程之间通讯的一种很常见的方法,很多时候都会用到. package com.lab.activity; import android.app.Activity; import ...
- Handler机制原理图、源码、使用!!!!!
android的消息处理机制——Looper,Handler,Message (原理图.源码) 转自:http://my.oschina.net/u/1391648/blog/282892 在开始讨 ...
- Android Handler 机制 - Looper,Message,MessageQueue
Android Studio 2.3 API 25 从源码角度分析Handler机制.有利于使用Handler和分析Handler的相关问题. Handler 简介 一个Handler允许发送和处理M ...
- 简述Handler机制
我会对android的消息处理有三个核心类逐步介绍,他们分别是:Looper,Handler和Message.其实还有一Message Queue(消息队列),知道它是队列即可,就像我们所熟知的数组, ...
- android Handler机制之ThreadLocal详解
概述 我们在谈Handler机制的时候,其实也就是谈Handler.Message.Looper.MessageQueue之间的关系,对于其工作原理我们不做详解(Handler机制详解). Messa ...
- Android Handler机制剖析
android的handler机制是android的线程通信的核心机制 Android UI是线程不安全的,如果在子线程中尝试进行UI操作,程序就有可能会崩溃. Android中的实现了 接收消息的& ...
- Android Handler 机制总结
写 Handler 原理的文章很多,就不重复写了,写不出啥新花样.这篇文章的主要是对 handler 原理的总结. 1.Android消息机制是什么? Android消息机制 主要指 Handler ...
- 10分钟了解Android的Handler机制
Handler机制是Android中相当经典的异步消息机制,在Android发展的历史长河中扮演着很重要的角色,无论是我们直接面对的应用层还是FrameWork层,使用的场景还是相当的多.分析源码一探 ...
随机推荐
- vue router.push(),router.replace(),router.go()
1.router.push(location)=====window.history.pushState 想要导航到不同的 URL,则使用 router.push 方法.这个方法会向 history ...
- selenium_采集药品数据2_采集所有表格
Python爬虫视频教程零基础小白到scrapy爬虫高手-轻松入门 https://item.taobao.com/item.htm?spm=a1z38n.10677092.0.0.482434a6E ...
- java了解哪些锁
问题: 1.Java里的锁了解哪些? 说了Lock和synchronized 它们的使用方式和实现原理有什么区别呢?使用的话,synchronize用于方法和代码块,可以锁对象和类以及方法,Lock ...
- logback异步输出日志(生产者消费者模型),并非批量写入日志。
一直对logback异步输出日志误解为异步批量写入日志. 今天看了源代码. 首先logback的异步日志是如何配置的: <!-- 管理端用户行为日志异步输出,异步的log片段必须在同步段后面,否 ...
- 无线DOS攻击
1.无线连接状态 IEEE 802.11定义了一种客户端状态机制,用于跟踪工作站身份验证和关联状态.无线客户端和AP基于IEEE标准实现这种状态机制.成功关联的客户站停留在状态3,才能进行无线通信.处 ...
- Python实现Plugin
1. Plugin与Python 插件的历史最早可追溯至1970年代,它是一种程序组件,通过和应用程序的互动,为应用程序增加一些所需要的特定的功能[维基].插件允许第三方开发者对已有的程序功能进行扩展 ...
- Postfix 邮件服务 - DNS服务
DNS 服务 (系统需要配置静态 IP 地址) yum install bing* -y 一.配置 NDS 域名解析: 直接添加以下内容: [root@mail ~]# cat /etc/named. ...
- python - 系统交互操作(subprocess)
本文摘于云游道士 链接:https://www.cnblogs.com/yyds/p/7288916.html 个人简化,便于查询. 命令行指令的执行通常有两个比较关注的结果: 命令执行的状态码--表 ...
- Python 入门基础19 --面向对象、封装
2019.04.17 一.面向对象与面向过程 二.名称空间操作 三.类与对象的概念 四.语法 五.对象查找属性的顺序 2019.04.18 1.类与对象的所有概念:__init__方法 2.类的方法与 ...
- 深入解析Java AtomicInteger 原子类型
深入解析Java AtomicInteger原子类型 在进行并发编程的时候我们需要确保程序在被多个线程并发访问时可以得到正确的结果,也就是实现线程安全.线程安全的定义如下: 当多个线程访问某个类时,不 ...