Android中事件上层的分发、拦截、处理还是比较好理解的,那么事件是如何从点击屏幕传到Activity,再有Activity分发给它自己的View的呢?
这里可能要分为两层:1、手机点击屏幕 事件传回--> Activity;2、Activity如何分发给子ViewGroup、View?
一、关于屏幕点击后的流程看图:
image.png二、屏幕点击后,事件如何监听?如何分发?
1.1 在深入看底层代码前我们先要了解几个知识。
- 1、屏幕事件有驱动保存在/dev/input/event0文件中
-
2、底层对/dev/input/event0主要使用Epoll+iNotify机制监听
image.png
1.2 下图是SystemServer进程开始IMS后,Native监听到事件后,准备由SystemServer进程发送到App进程的Activity阶段。
- 1、SystemServer实例化了InputManagerService实例,而上层的IMS实际依赖Native层的IMS来起作用。
- 2、Native层IMS会实例化一个EventHub和InputManager实例,EventHub主要封装了Epoll和iNotify机制,用来实现对/dev/input文件进行监控
- 3、InputManager构造方法中会实例InputReader和InputDispatcher,它们分别对事件读取和分发
- 4、并且新建两个线程InputReaderThread和InputDispatcherThread来处理有关读取事件和分发事件的事项
- 5、InputReaderThread线程开启后,通过epoll_wait阻塞,只到有事件发生(epoll_ctl)就会继续执行,封装事件,并将事件存储在mInboundQueue队列中。
- 6、InputDispatcherThread线程开启后,会去mInboundQueue队列中取事件,有就开始分发
- 7、因为此时IMS处于SystemServer进程,事件要发送给Activity(App进程)。这是跨进程通信。但是他这里不是使用Binder来通信,而是使用的SocketPair。
- 8、下图到了InputTransport.cpp publishMotionEvent()方法中 mChannel -> sendMessage(&msg)就是开始向上层Activity传递事件了。
三、Native底层获取信息后,如何跨进程通信传给上层App的Activity?
3.1 SystemServer进程和App进程建立链接用于事件传递
- 1、前面知道ActivityThread调到了handleResumeActivity方法,通过mWM.addView。最终会到ViewRootImpl的setView方法。
- 2、setView方法里,通过Session通信来到了WMS.addWindow
- 3、WMS.addWindow会调用到WindowState.openInputChannel方法
- 4、WindowState.openInputChannel会通过InputChannel.openInputChannelPair去底层创建两个SocketPair实例,一个用于写,一个用于读取。
- 5、创建好的两个SocketPair,会同时作用于一块区域,一个给Native层用于写事件,一个会调给上层用于读事件。
- 6、到这里就是建立好了SystemServer进程和App进程之间的链接,它们可以通信了。
3.2 链接建立好后,Native层事件会调给Activity
- 1、回到ViewRootImp.setView方法,在建立链接后,会实例化一个WindowInputEventReceiver对象,它将用于接受底层发送过来的事件。
- 2、WindowInputEventReceiver继承至InputEventReceiver,InputEventReceiver构造方法中会调用nativeInit,会对应构建一个NativeInputEventReceiver实例。并将InputChannel和MessageQueue传入。
- 3、NativeInputEventReceiver就类似于Handler机制,在consumeEvents中收到InputDispatcher发出的事件。将会回调InputEventReceiver.java的dispatchToucheEvent方法
- 4、然后因为WindowInputEventReceiver是InputEventReceiver子类,会调用到WindowInputEventReceiver的onInputEvent方法。
- 5、一路调用最终回到ViewPostimeInputStage的processPointerEvent方法
- 6、而processPointerEvent方法中会调用View的dispatchPointerEvent方法
- 7、dispatchPointerEvent方法中会调用dispatchTouchEvent方法,而在ViewRootImpl中mView实际是DecorView。
- 8、那么就进入到DecorView的dispatchTouchEvent方法,在该方法中会调用mWindow.getCallback().dispatchTouchEvent方法。
- 9、而在Activity的attach方法中又mWindow.setCallback(this),所以mWindow.getCallback()其实就是Activity对象,Activity也实现了Window.Callback接口。
- 10、到这事件就到了Activity的dispatchTouchEvent来了,接下来就是应用层,Activity分发给它的子ViewGroup和子View了。
网友评论