Handler机制
1.定义
Handler主要是负责线程之间的通信,提供用来更新ui的一套机制,也是一套消息处理机制
2.为什么使用handler
因为在Android开发过程中,为了UI线程在操作中是安全的,规定了主线程更新UI,但是在实际开发中,回出现多个线程并发操作UI组件的操作,会导致线程不安全,所以我们要用到Handler机制,在线程要更新UI时,通过Handler通知主线程,从而在主线程中更新UI,避免线程操作不安全的问题
(1)Handler(消息接收/处理者)负责的内容是消息的发送和具体处理流程,一般使用的时候由开发者重写handlerMessage函数,根据自定义的不同message做不同的ui更新操作
因发送消息到消息队列的方式不同而不同可以通过
Handler.sendMessage(),和handler.post()
handlerMessage()在该方法中分为种:
新建handler子类class mHandler extends Handle
匿名内部类Handler mhandler = new Handler()
handler.post():
创建一个工作线程,实现Runnable接口,实现run方法,处理耗时操作
创建一个handler,通过handler.postDelay,投递创建的Runnable,在run方法中进行更新UI操作
在主线程中创建Handler实例 private Handler mhandler = new mHandler();
// 步骤2:在工作线程中 发送消息到消息队列中 & 指定操作UI内容 // 需传入1个Runnable对象
mHandler.post(new Runnable() {
@Override
public void run() {
… // 需执行的UI操作
}
// 步骤3:开启工作线程(同时启动了Handler) // 多线程可采用AsyncTask、继承Thread类、实现Runnable
而Post得一系列方法最终通过send的一系列方法来实现的,而send的一系列方法最终是通过sendMessageAtTime方法来实现的,Handler发送一条消息,就在消息队列中插一条消息。
(2)Message(消息)
是在线程之间传递的消息,它可以在内部携带少量的数据,用于线程之间交换数据
(3)MessageQueue(消息队列)
它主要用于存放所有用过Handler发送的消息,这部分消息会一直存在与消息队列中,等待被处理,每个线程中只会有一个MessageQueue对象
工作原理:
MessageQueue消息队列是通过一个单链表的数据结构来维护消息列表,它有两个方法,enqueueMessage()和next()
enqueueMessage主要是根据时间的顺序向单链表中插入一条消息
next方法是一个无限循环的方法,如果有消息返回这条消息,并从链表中移除,而没有消息则一直阻塞在这里
(4)Looper(消息泵)
每个线程通过Handler发送的消息都保存在MrssageQueue中,Looper通过调用loop()方法就会进入一个无限循环当中,然后每当发现MessageQueue中存在一条消息,就会将它取出并传递到Handler的handlerMessage()方法中,每个线程中只会有一个Looper对象
工作原理:
系统调用了Looper.prepareMainLooper()来创建主线程的Looper以及MessageQueue并通过Looper.loop()来开启主线程的消息循环,在這个循环中不断的从MessageQueue的next方法获取消息,而next方法是一个阻塞操作,没有消息的时候一直在阻塞,当有消息了通过dispatchMessage()发送消息给Handler对象
(5)ThreadLocal:
MessageQueue对象和Looper对象在每个线程中都只会有一个对象,怎么来保证他们唯一,就通过ThreadLocal来保存,ThreadLocal是一个线程内部的数据储存类,通过它可以在指定线程中存储数据,数据储存以后,只有在指定的线程中可以获取到储存数据,对于其他线程来说则无法获取数据。
总结
主线程创建一个Handler对象,并重写handlerMessage方法,然后当在子线程中需要进行更新UI的操作,我们就创建一个Messaage对象,并通过handler发送这条消息出去之后这条消息被加入到MessageQueue队列中等待被处理,通过Looper对象会一直尝试从MessageQueue中取出待处理的消息,最后分发在Handler的handlerMessage()方法中
原理:
handler发送Message(消息)至MessageQueue(模拟队列),由Looper(循环器)不断循环取出。然后通知Handler处理。这便是整个的消息机制。
https://blog.csdn.net/guiying712/article/details/53412281
Looper.looper不会造成死循环?
epoll+pipe,有消息就依次执行,没消息就block住,让出CPU,等有消息了,epoll会往pipe中写一个字符,把主线程从block状态唤起,主线程就继续依次执行消息
就像一辆车在圆形赛车道上跑,一边跑一边执行任务,比如开到市中心买瓶水,任务完成又回到刚刚离开的地方,继续各种执行买水的任务,直到没有任务了,行了,跑一圈回到起点。睡觉,有任务叫醒你,你又开始跑一圈。边跑边接单。