时人不识凌云木,直待凌云始道高。这篇文章主要讲述android 消息机制相关的知识,希望能为你提供帮助。
Handler Message Looper MessageQueue
①Looper
MessageQueue的创建
主线程的消息队列是由系统创建的(prepareMainLooper)
ActivityThread类的main方法中 调用prepaerMainLooper
prepareMainLooper 程序员不要调 如果调用了会抛出异常
prepareMainLooper调用了Looper.prepare()方法;
这个方法中先判断当前线程是否已经有Looper了 如果有抛异常
如果没有 创建一个Looper对象通过一个ThreadLocal保存(线程单例 一个线程对应唯一的对象)
在Looper创建的过程中又new MessageQueue并且通过final类型的成员变量保存起来 实现一个Looper对应一个消息队列
这样 一个线程对应唯一的Looper 对应唯一的消息队列
【android 消息机制】② Looper让消息队列循环起来
Looper.loop()方法
这里有一个死循环 这个死循环不会阻塞主线程 正是因为用了这个死循环 程序才能一直运行不会退出
在Looper.loop()方法中 就是不断的到消息队列中取消息( queue.next() 阻塞的) 如果没有消息或者当前有消息但是没到要执行的时间 queue.next()方法不会有返回值 会一直阻塞
取出消息之后就交给handler去处理
msg.target.dispatchMessage()方法
③Handler处理消息
public void dispatchMessage(Message msg) {if (msg.callback != null) {// 如果msg 的Runnable类型的成员变量 callback不为空 直接执行这个runnalbe中的run方法 不会执行handler的handlemessagehandleCallback(msg); } else {//如果msg 的Runnable类型的成员变量为空if (mCallback != null) {//再判断handler的成员变量mCallback(CallBack类型)if (mCallback.handleMessage(msg)) { //如果mCallback不为空 先执行CallBack接口中的handleMessage方法 根据这个handleMessage的返回值决定是否执行Handler的handleMessagereturn; }}handleMessage(msg); }}
?
④ Handler的创建
会先取出当前线程所对应的Looper和MessageQueue 通过final类型的成员变量保存起来
确定哪个线程创建的handler消息就会放到当前线程的消息队列中
如果创建handler的时候想指定这个handler对应的消息队列(线程)
Handler(Looper);
子线程中使用消息机制 在new Handler之前一定要先Looper.prepare()方法 再去调用Looper.loop()方法
子线程使用Handler 可以让子线程执行多个可以排序的任务
子线程中使用消息机制之后 通过Looper.quit()方法退出死循环
⑤通过handler发送消息
发送消息最终 sendMessageAtTime(当前的系统时间+延迟) sendMessageAtFrontofQueue(立刻执行消息 传入的时间0)
消息队列中消息是如何排序的 按照时间的先后顺序
MessageQueue的数据结构 单链表 只保存了所有消息的第一条消息 (最优先执行的消息)
通过一个成员变量 mMessages 保存第一条消息
Message对象都有一个成员变量 next 通过这个next就可以指向当前消息的下一条消息
sendMessageAtTime 和 sendMessageAtFrontofQueue 都会调用MessageQueue的enqueueMessage方法
就是把消息在消息队列中按照要执行的先后时间进行排序
⑥Message的创建和回收
Message.obtain(); 从消息池中获取消息 而不是new Message();
有消息池 最多缓存50条 超过50条就不缓存了
消息池的数据结构单链表 静态 Message变量 spool 记录了消息池的第一条消息
当消息处理之后 会调用msg.recycle方法 回收消息 把消息所有的成员变量置0/null 然后放到消息池中
推荐阅读
- 打造自己的Android常用知识体系
- Android Studio 将文件打包成APK
- Array.apply(arr,Array())
- java bean 对象属性复制框架BeanMapping-01-入门案例
- Android应用程序版本升级时签名冲突
- 配置IIS服务器提供APP文件下载
- 使用R进行时间序列分析
- 在SQLite中修改日期函数
- R的基本编程技巧