Android消息机制的设计思路:
Android消息机制利用了epoll.wait(timeout)来进行时间片阻塞,延迟执行和事件监听。我们在java层和native各维护了一个消息队列,唤醒时间一起参与计算,时间最短者为timeout参数。当有可立即执行的消息传入时,会直接通过wake()函数唤醒epoll,否则将在timeout超时后执行原定的延迟任务。这样,既能监听即时消息又可以执行延时任务。
有时,一些消息需要被暂停,有一些消息又需要被优先执行。于是有了Barrier(消息屏障)。Barrier是特殊的message,它的target=null。当它在队首时,将会阻隔同步消息,但又放行异步消息。同步消息和异步消息分别由同步Handler和异步Handler发送,Handler在初始化成同步或是异步之后不能更改,这样可以避免逻辑混乱。
Looper.prepare()会对MessageQueue,Looper,NativeMessageQueue,NativeLooper,epoll等核心组件进行初始化。初始化之后,Looper.loop()会启动死循环,不断获取Message去执行。在loop()的死循环里,queue.next()方法中也有一个死循环,用于获取可以立即执行的Message。并且,在每执行一个Message之后,如果没有可立即执行的Message,将会启动IdelHandler执行任务。queue.next()中调用nativePollOnce()也有一个死循环,会从response中获取符合条件的response执行pollInnner()。在PollInner()中,会执行epoll.wait()实现监听阻塞。
具体过程:首先,线程调用Looper.prepare(),Looper.loop()两个方法。在Looper.prepare()中,会创建一个Looper对象并存入线程ThreadLocal的固定位置。Looper构造函数传入一个quitAllowed参数,决定该Looper是否可以退出(main线程是不可退出的)。Looper构造函数中,创建MessageQueue,MessageQueue的构造中,储存quitAllowed值,并调用nativeInit()。nativeInit()方法中创建一个native层的NativeMessageQueue,并且通过JNI保存进Java层MessageQueue的mPtr中。NativeMessageQueue的构造中获取了一个Native层的Looper,并存入了线程本地。Handler发消息最终调用到sendMessageAtTime(),其中获取到消息队列,然后调用enqueueMessage,把msg的tartget设为自己。这里相当于把回调函数注册到了message中。在调用queue.enqueueMessage之前,会进行同步异步判断,将该消息设置为同步或者异步消息。