四个关键角色:Message、Handler、MessageQueue、Looper。
需要传递的消息放在Message中。Message有一个成员变量target引用它绑定的Handler对象。
Handler在创建时需要一个Looper对象,Handler会在sendMessage方法中将Message添加到这个Looper的MessageQueue中排队等待触发回调。
每个线程只能有一个Looper,它在Looper.prepare()初始化时会给自己创建一个MessageQueue,然后Looper.loop()开启一个死循环,不停地从MessageQueue中取出Message,再通过Message的target获取到对应的Handler,调用Handler的handleMessage方法,从而执行回调。
MessageQueue是一个按时间排序的单向链表,负责存放等待Looper处理的Message。Handler调用MessageQueue的enqueueMessage()方法添加Message,Looper调用MessageQueue的next()方法获取Message。
建议通过Message.obtain()从缓存池中获取Message对象复用,而不要直接new,避免创建太多对象,减轻GC压力。Message缓存池的最大容量是50个。Looper在调用完handleMessage方法后会回收Message对象。
当MessageQueue中没有Message时,Looper并不会死循环一直空转占满CPU导致卡死ANR,而是Looper所在的线程会进入阻塞休眠状态,不会执行循环体。这是因为Looper调用MessageQueue的next()方法获取Message,而next()中判断如果MessageQueue为空,则调用nativePollOnce方法阻塞,该方法是在native层(C++)实现的,因此是调用Linux的epoll机制进行阻塞。
唤醒的时机在Handler添加Message时调用的enqueueMessage当中,里面会调用nativeWake方法,唤醒epoll阻塞的线程。