如何启动looper,如何处理一条普通java层消息
Android应用进程都是由Zygote克隆出来的,在ZygoteInt的main中会通过反射调用ActivityThread的main方法。
ActivityThread中的main方法会调用Looper的prepareMainLooper,创建looper对象,并存在ThreadLocal中。在Looper的构造函数中,会创建MessageQueue,MessageQueue的构造函数中会创建MessageQueueNative(暂时忽略)。
创建完looper后,main方法中会创建ActivityThread对象,然后调用looper的loop方法启动起looper。
looper启动起来后,会去调用messagequeue的next方法获取message。next方法中会先调用nativePollOnce0代表不休眠,-1代表永久休眠,大于0代表休眠时间,注意这个仅代表java层的意愿,native层不一定会照办(暂时忽略)。
如果有handler发消息过来,会调用messagequeue的equeueMessage方法,然后调用nativeWake唤醒线程,这时之前looper.next就收到返回的消息了,在looper中,调用消息target的dispatchMessage方法处理消息。
messagequque.next java层的流程
java层有3种消息:普通消息,异步消息,屏障消息,还有一个idleHandler
当looper调用messagequeue的next时,先获取下一条消息,如果下一条消息target==null,说明是一条屏障消息,此时looper只会处理异步消息,哪怕异步消息处理完了,也不会处理普通消息。需要手动移除屏障消息,才能开始处理普通消息。等没有需要立即处理的普通消息或者异步消息,就会开始处理idleHandler。
nativePollOnce底层逻辑
在Android中除了java层有Handler、MessageQueue和looper,native层也有。
java层创建MessageQueue时,会调用nativeInit,创建MessageQueueNative,MessageQueueNative构造函数中会创建looper,以类似java层ThreadLoacal的方式存在线程中。
创建native looper是,会调用一个非常关键的方法,rebuildEpollLocked。该方法主要是使用mWakeEventFd监听EPOLLIN事件,然后调用epoll_ctl把mWakeEventFd关联到mEpollFd上。当java层的MessageQueue调用nativePollOnce时,MessageQueueNative调用looper的pollOnce进入一个死循环,改循环由pollInner的返回值决定是否要跳出。pollOnce中先处理不带callback的request事件,后进入pollInner根据native和java的休眠时间,计算出真正需要休眠的时间,然后调用epoll_wait休眠,休眠被唤起后,读取mEpollFd上面的事件,如果是mWakeEventFd,就吧内容读取出来。如果是其他,将request加入reponse队列,然后处理本地消息队列上的消息,最后处理response返回。如果是java层要主动唤起,则调用nativeWake,然后调用looper的wake方法,往mWakeEventFd中写入1,pollInner中的epoll_wait就会返回。从而唤起线程。
总结
android中消息分为java层消息和native层消息。java层和native层主要是通过messagequeue关联起来的,优先处理native层消息,然后处理java层异步消息,最后处理idleHandler。native层looper优先处理不带返回的request(在mResponses中),然后处理native消息,最后处理带返回的request(mEpollFd上面的事件)
相关源码
www.androidos.net.cn/android/9.0… www.androidos.net.cn/android/10.… www.androidos.net.cn/android/10.… www.jianshu.com/p/91a4b7975…
问题点
java层异步消息什么时候用? native消息有哪些? native不带返回的request是什么? native带返回的request又是什么? 触摸事件是在哪里处理的? vsync事件是在哪里处理的? 下篇文章研究这些问题。