===================================================================
Handler机制:
- handler->sendMessage // 发送消息
- messasgeQueue.enqueueMessage //消息队列存入消息
- looper.loop()-> messasgeQueue.next() // 从消息队列取
- handler.dispatchMessage()->handler.handleMessage // 处理取出的消息
① 创建Handler
②创建Message
可以直接new Message 但是 Message.obtain 更好。因为可以检查是否有可以复用的Message,用过复用避免过多的创建、销毁Message对象达到优化内存和性能的目的。
③创建Looper
⑴Looper.prepare 创建Looper对象;
⑵Looper.myLooper 获取Looper对象
⑶Looper.loop 不断的轮询,从消息队列中取出消息,交给Handler处理
prepare有两个重载的方法,主要看 prepare(boolean quitAllowed)
quitAllowed的作用是在创建MessageQueue时,标识消息队列是否可以销毁,主线程不可被销毁。
④获取Looper对象
怎么保证一个线程只有一个Looper的呢????
创建MessageQueue以及Looper与当前线程的绑定
整个过程梳理:
一:创建Looper对象
(Looper.prepare()—>prepare方法里,sThreadLocal.set(new Looper(quitAllowed)))
a. Looper的构造方法会创建消息队列对象,以及获取当前线程
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed); // 标识消息队列是否可以销毁
mThread = Thread.currentThread();
}
b. MessageQueue 的构造方法,会给quitAllowed和mPtr 赋值
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
mPtr = nativeInit();
}
二:创建Handler对象(handler 的构造方法,获取到当前线程的looper对象和消息队列)
三:创建消息
可以直接new Message 但是有更好的方式 Message.obtain。因为可以检查是否有可以复用的Message,用过复用避免过多的创建、销毁Message对象达到优化内存和性能的目的。
四,发送消息,send/post发消息,最终都是调用MessageQueue.enqueueMessage(msg, uptimeMillis):
类MessageQueue,这个类是所有消息的存储仓库,在这个仓库中,我们如何的管理好
消息,这个就是一个关键点了。消息管理就两点:
- 存:消息入库(enqueueMessage)
- 取:消息出库/取出消息(next),
这两个接口是确保线程安全的主要档口。
next函数的疑问:
我们从线程里面取消息,而且每次都是队列的头部取,那么它加锁是不是没有意义呢?
答案是否定的,我们必须要在next里面加锁,因为,这样由于synchronized(this)作用范围是所有 this正在访问的代码块都会有保护作用,也就是它可以保证 next函数和 enqueueMessage函数能够实现互斥。这样才能真正的保证多线程访问的时候messagequeue的有序进行。
handler 发送消息和处理消息是同一个队列吗????
------答:个人分析是的,loop的方法,变历消息队列,这个消息队列也是Looper的成员变量给赋值的。如下,发送消息时,消息队列queue的值mQueue,也是来源于Looper的构造方法。
五,处理消息,
在handleMessage(Message)方法中,我们可以拿到message对象,根据不同的需求进行处理,整个Handler机制的流程就结束了。
小结:
handler.sendMessage 发送消息到消息队列MessageQueue,然后looper调用自己的loop()函数去轮询MessageQueue里面的每个Message,当Message达到了可以执行的时间时,就会调用message绑定的Handler来处理消息。
工作线程 发给 主线程:
主线程 发给 工作线程