事件在Android Framework层的完整流程

在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中,具体是怎么传递事件的呢?这个时候就需要慢慢分析源码了。下面用图表示流程,具体代码以后有时间加上。

Created with Raphaël 2.2.0 MessageQueue.nativePollOnce() native调用处理... InputEventReceiver: dispatchInputEvent() ViewRootImpl$WindowInputEventReceiver: onInputEvent() ViewRootImpl: enqueueInputEvent() ViewRootImpl: doProcessInputEvents() ViewRootImpl: deliverInputEvent() ViewRootImpl$InputStage: deliver() ViewRootImpl$ViewPostImeInputStage: onProcess() ViewRootImpl$ViewPostImeInputStage: processPointerEvent() View: dispatchPointerEvent() DecorView: dispatchTouchEvent() Window.Callback(Activity/Dialog): dispatchTouchEvent() PhoneWindow: superDispatchTouchEvent() DecorView: superDispatchTouchEvent() ViewGroup: dispatchTouchEvent()

如果怕自己看源码静态分析的时候跟着各种跳转被绕进去,这里分享一个小技巧:准备好手机或模拟器,我们新建一个空项目,gradle中的compileSdkVersion设置为和手机或模拟器系统版本一致,并通过Studio的SDK Manager下载好对应版本源码;只需要在MainActivity中放一个Button,在ViewGroup的dispatchTouchEvent方法中打上断点,然后Debug运行应用或运行后Attach,点击一下Button,就可以看到应用进入断点了,从Debugger窗口的方法调用栈,我们就能清晰的看到事件的整个传递过程了。点击调用栈中的方法,就能清楚的看到具体的调用位置了。
在这里插入图片描述

发布了29 篇原创文章 · 获赞 8 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/China_Style/article/details/104830990