以下分析基于:android-28(Android 9.0)源码。
在MessageQueue中,有两个重要的方法:一个是enqueueMessage
,负责将消息加入队列;一个是next
,负责从消息队列中取出一个待处理的消息。
// android.os.MessageQueue
MessageQueue {
boolean enqueueMessage(Message msg, long when) {
// ...
}
Message next() {
// ...
for (;;) {
// ...
nativePollOnce(ptr, nextPollTimeoutMillis);
// ...
}
}
}
在从消息队列中取出下一条消息时,会调用nativePollOnce
方法,进入native层,在native中经过一系列处理,最终会回调到Framework层InputEventReceiver.java的dispatchInputEvent
方法。
native中的处理及整个完整的过程,欢迎参考Gityuan的Input系统—事件处理全过程一文。
android.view.InputEventReceiver.java:
// Called from native code.
@SuppressWarnings("unused")
private void dispatchInputEvent(int seq, InputEvent event, int displayId) {
mSeqMap.put(event.getSequenceNumber(), seq);
onInputEvent(event, displayId);
}
那在Framework中,具体是怎么传递事件的呢?这个时候就需要慢慢分析源码了。下面用图表示流程,具体代码以后有时间加上。
Debug分析
如果怕自己看源码静态分析的时候跟着各种跳转被绕进去,这里分享一个小技巧:准备好手机或模拟器,我们新建一个空项目,gradle中的compileSdkVersion
设置为和手机或模拟器系统版本一致,并通过Studio的SDK Manager下载好对应版本源码;只需要在MainActivity中放一个Button,在ViewGroup的dispatchTouchEvent方法中打上断点,然后Debug运行应用或运行后Attach,点击一下Button,就可以看到应用进入断点了,从Debugger窗口的方法调用栈,我们就能清晰的看到事件的整个传递过程了。点击调用栈中的方法,就能清楚的看到具体的调用位置了。