流程
1.在Handler 初始化时,会获取当前线程的looper, 以及 MessageQueue;
2.handler.SendMessage 方法最终会调用MessageQueue.enqueueMessage(), 将Message插入到MessageQueue链表中,并将Handler 本身赋值给Message 对象的target属性;
3.MessageQueue在将Message插入到队列后,Looper里的Looper方法会检测到新消息出现,并开始处理消息;
4.Looper.Loop方法从消息队列里面获取到message后,通过target属性拿到Handler对象,正是我们enqueueMessage放入的handler 对象;
5.调用handler对象的dispatchMessage方法,最终会走到我们继承于Handler的handlerMessage方法,来处理具体的业务;
其他问题
线程切换
记住:消息的执行是在looper的线程,消息的发送线程如果和创建looper的线程不一致,那才是多线程通信。
子线程sendMessage,怎么切到主线程的? Looper 发现有 message 插入到 MessageQueue 中,便取出 message 执行相应的逻辑
因为 Looper.loop()是在主线程中启动的,所以则回到了主线程中,达到了切换线程的目的
什么是IdleHandler
ActivityThread.handleResumeActivity()中,在 onResume 方法执行完毕后,调用 Looper.myQueue().addIdleHandler(new Idler()) ,去执行一些资源回收,日志打印等不那么着急的任务。除此之外,在做项目 性能优化 的时候也可以使用 IdleHandler,它在主线程空闲时执行任务,而不影响其他任务的执行。
创建Message 为什么推荐使用obtain() 方式获取Message对象,而不推荐使用new Message()?
这里涉及到池的技术的应用: Message中维护了一个消息池,消息使用完就会回收。减少对象创建和销毁的开销;java的线程池也是这种思想,设计模式里的享元模式