一、事件从Kernel层传递到Framework层
1.准备工作:WindowManagerService首先通过native方法创建InputManager,InputManager调用Kernel层的InputSystem创建EventHub、InputReader和InputDispatcher。
2.建立连接:ViewRootImpl在调用setView的时候创建一个InputCannel对象,然后通过调用WindowManagerService的addWindow方法创建一对InputChannel对象,两个InputChannel被注册到Kernel层,实现全双工管道。WindowManagerService将其中一个InputChannel对象传递给之前创建的InputManager,ViewRootImpl内的InputChannel对象交由ViewRootImpl$WindowInputEventReceiver保存。
3.传递事件:Kernel层将自己不处理的事件记录到对应的事件文件之中,InputReader从事件记录文件种读取事件,交给InputDispatcher,InputDispatcher将事件转发给InputPublisher,InputPublisher拿到WindowManagerService传递来的InputCannel(输入端)向ViewRootImpl内持有的InputCannel(输出端)对象发送事件通知(一个字节),输出端通过共享内存获取实际的事件内容,通过InputEventReceiver.dispatchInputEvent方法将事件分发给ViewRootImpl$WindowInputEventReceiver,由其中onInputEvent方法处理。
二、事件传递至当前Activity(以下只考虑同步且立即处理的情况)
1.ViewRootImpl$WindowInputEventReceiver.onInputEvent调用ViewRootImpl内部的enqueueInputEvent方法,判断事件是否需要立即执行,如果立即处理则执行doProcessInputEvents,否则scheduleProcessInputEvents。
2.doProcessInputEvents方法内执行deliverInputEvent处理事件(队列),选择对应的InputStage处理事件(调用deliver方法),如果没有合适的InputStage对象则结束事件。对应的InputStage对象分别为:
1)异步处理:mSyntheticInputStage;
2)同步直接处理:mFirstPostImeInputStage;
3)同步需预处理:mFirstInputStage;
3.mFirstPostImeInputStage内部链式调用EarlyPostImeInputStage.onProcess(获取焦点),NativePostImeInputStage.onProcess(检查是否立即处理),ViewPostImeInputStage.onProcess(分发事件)
4.ViewPostImeInputStage.onProcess通过processPointerEvent内调用DecorView的dispatchPointerEvent(View.class内的方法)方法,将事件传递给DecorView.dispatchTouchEvent方法,DecorView.dispatchTouchEvent内再去调用Window.Callback.dispatchTouchEvent,而其中的Window.Callback就是对应的Activity;
三、事件由Activity下发至ViewGroup(实际也就是DecorView)
1.如果是MotionEvent.ACTION_DOWN事件,需要先执行onUserInteraction方法,此方法没有返回值,不会对后面事件传递造成直接影响,默认为空实现。
2.调用Window.superDispatchTouchEvent方法,Activity默认的Window为PhoneWindow,其superDispatchTouchEvent方法为调用DecorView的superDispatchTouchEvent方法。
3.DecorView.superDispatchTouchEvent调用ViewGroup.dispatchTouchEvent,接下来事件将按照ViewGroup的默认分发机制下发。
四、ViewGroup事件分发
这部分内容在网上可以查到的资料比较多,下面的这张事件的U型传递图还是比较详尽的(来自参考文章)。
事件分发机制参考文章:
网友评论