Android中事件上层的分发、拦截、处理还是比较好理解的,那么事件是如何从点击屏幕传到Activity,再有Activity分发给它自己的View的呢?
这里可能要分为两层:1、手机点击屏幕 事件传回–> Activity;2、Activity如何分发给子ViewGroup、View?
一、关于屏幕点击后的流程看图:
二、屏幕点击后,事件如何监听?如何分发?
1.1 在深入看底层代码前我们先要了解几个知识。
-
1、屏幕事件有驱动保存在/dev/input/event0文件中
-
2、底层对/dev/input/event0主要使用Epoll+iNotify机制监听
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了。
作者:天上飘的都是浮云
原文链接:(https://www.jianshu.com/p/84cf443cfa75)
最后
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
全套视频资料:
一、面试合集
二、源码解析合集
三、开源框架合集
欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓