Framework学习

View

Android APP中,所有的用户界面元素都是由ViewViewGroup的对象构成的。View是绘制在屏幕上的用户能与之交互的一个对象。而ViewGroup则是一个用于存放其他View(和ViewGroup)对象的布局容器! Android为我们提供了一个ViewViewGroup子类的集合,集合中提供了一些常用的输入控件(比如按钮和文本域)和各种各样的布局模式(比如线性或相对布局)。

View的绘制流程

1. measure在measure过程中,View会通过调用measure方法来计算自身的尺寸大小。在measure方法中,View会根据父容器的MeasureSpec以及自身的LayoutParams来计算自身的尺寸。

2. layout在layout过程中,View会通过调用layout方法来确定自己在父容器中的位置和大小。在layout方法中,View会根据父容器的尺寸以及自身的尺寸来确定自己在父容器中的位置和大小。

3. draw在draw过程中,View会通过调用draw方法来进行绘制。在draw方法中,View会先绘制自己的背景,然后再绘制自己的内容,最后再绘制自己的前景。在绘制自己的内容时,View会调用自己的onDraw方法来进行绘制。

Input事件在View的派发

输入事件是从底层上报至 (IMS)处理,IMS由SystemServer创建,其功能实现主要在Native层。WMS的职责之一就是输入系统的中转站,WMS作为Window的管理者,会配合IMS将输入事件交由合适的Window来处理。WMS在app端setView的时候会创建了一对Socket连接,IMS中的InputDispatcher利用这个Socket连接和app端通信,也就是input事件传递到View体系中进行处理了。

Input输入事件在ViewGroup中的传递流程如图所示,在其逻辑中会判断是否拦截处理, 如果拦截处理则该事件由该对象消费,不再向子View传递;如果不拦截,则向子view进行传递。

InputManagerService

Linux内核:接受输入设备的中断,并将原始事件的数据写入设备节点中设备接电,作为内核与 IMS 的桥梁,将原始事件的数据暴露给用户空间,以便 IMS 可以从中读取事件;

EventHub:直接访问所有的设备节点,通过一个名为 getEvents() 的函数将所有输入系统相关的待处理的底层事件返回给使用者,包括原始输入事件,设备节点的增删等;

InputReader:IMS 中的关键组件之一,它运行在一个独立的线程中,负责管理输入设备的列表和配置,以及进行输入事件的加工处理,它通过其线程循环不断地通过 getEvents() 函数从 EventHub 中将事件取出并进行处理,对于设备节点的增删事件,它会更新输入设备列表与配置;对于原始输入事件,InputReader对其进行翻译,组装,封装为包含更多信息,更多可读性的输入事件,然后交给InputDispatcher进行派发;

InputReaderPolicy:为 InputReader 的事件加工处理提供一些策略配置;

InputDispatcher:是 IMS 中的另一个关键组件,运行于一个独立的线程中,InputDispatcher 中保管来自 WMS 的所有窗口的信息,收到 InputReader 的输入事件后,会在其保管的窗口中寻找合适的窗口,并将事件派发给此窗口;

InputDispatcherPolicy:为 InputDispatcher 的派发过程提供策略控制,例如 HOME 键被 InputDispatcherPolicy 截取到 PhoneWindowManager 中处理,并阻止窗口收到 HOME 键按下的事件;

ViewRootImpl:对某些窗口,如壁纸窗口,SurfaceView 的窗口来说,窗口就是输入事件派发的终点,而对其他的如Activity,对话框等使用了 Android 控件系统的窗口来说,输入事件的终点是控件;

IMS(InputManagerService):主要负责键盘、触摸屏、鼠标等输入设备的事件输入及向焦点窗口的事件派发,过滤,拦截等功能。

Android系统中,输入事件是由InputManagerService服务来管理的,然后再以消息的形式来分发给应用程序处理。当用户触摸屏幕或者按键操作,首次触发的是硬件驱动,驱动收到事件后,将该相应事件写入到输入设备节点, 这便产生了最原生态的内核事件。接着,输入系统取出原生态的事件,经过层层封装后成为KeyEvent或者MotionEvent;最后,交付给相应的目标窗口(Window)来消费该输入事件。

IMS 的启动流程

创建新的IMS对象

SystemServer->ServerThread.run()--> com_android_server_input_InputManagerService.cpp-->nativeInit()

创建了 NativeInputManager 对象,该对象实现了 InputReaderPolicyInterface 与 InputDispatcherPolicyInterface 接口,创建 EventHub 和 InputManager,InputManager 创建了 InputReader 与 InputDispatcher 以及 InputReaderThread 与 InputDispatcherThread。

Android系统在启动的时候,会初始化zygote进程和由zygote进程fork出来的SystemServer进程。SystemServer在启动系统服务的过程中,会启动InputManagerService(IMS),IMS通过JNI调用,启动native层的Input模块。native层创建InputManager,并将其注册到 ServiceManager中,后面其他模块可以通过获取“inputflinger”的服务来远程调用它。之后,InputManager创建用于接收和派发Input事件的EventHub,InputReader和InputDispatcher等模块。

WindowManagerService

WindowManagerService,管理当前系统中所有的window窗口。它主管分配设备产生的touch事件、keydown事件,因为wms能知道当前系统中哪个window最适合来处理某个事件,硬件产生的某个事件最终是要被软件应用所消费的,那些view、button的按键事件就是通过window再传递给View体系来响应按键的。

SurfaceFlinger:SurfaceFlinger是一个独立的Service, 它接收所有Window的Surface作为输入,根据ZOrder, 透明度,大小,位置等参数,计算出每个Surface在最终合成图像中的位置,然后交由HWComposer或OpenGL生成最终的显示Buffer, 然后显示到特定的显示设备上。

Surface:在Android中,Window与Surface一一对应。 如果说Window关心的是层次和布局,是从设计者角度定义的类,Surface则从实现角度出发,是工程师关心和考虑的类。Window的内容是变化的,Surface需要有空间来记录每个时刻Window的内容。在Android的SurfaceFlinger实现里,通常一个Surface有两块 Buffer, 一块用于绘画,一块用于显示,两个Buffer按照固定的频率进行交换,从而实现Window的动态刷新。

Layer:Layer是SurfaceFlinger 进行合成的基本操作单元。Layer在应用请求创建Surface的时候在SurfaceFlinger内部创建,因此一个Surface对应一个 Layer, 但注意,Surface不一定对应于Window,Android中有些Surface并不跟某个Window相关,而是有程序直接创建,比如说 SurfaceView, 用于显示有硬件输出的视频内容等。当多个Layer进行合成的时候,并不是整个Layer的空间都会被完全显示,根据这个Layer最终的显示效果,一个Layer可以被划分成很多的Region。

https://img-blog.csdn.net/20160322144124034?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

当Surface绘制完成后会发出一个Invalidate的消息给Surfaceflinger的等待线程,当waitForEvent接收到消息后就会交给onMessageReceivered去处理,处理过程中会依次调用handleMessageTransaction、handleMessageInvalidate、handleMessageRefresh接口。

handleMessageTransaction——主要处理之前对屏幕和应用程序窗口的改动。窗口状态的改变只能在一个Transaction中进行。因为窗口状态的改变可能造成本窗口和其他窗口的可见区域变化,所以就必须重新来计算窗口的可见区域。在这个处理子过程中Android会根据标志位来对所有layer进行遍历,一旦发现哪个窗口的状态发生了变化就设置标志位以在将来重新计算这个窗口的可见区域。

handleMessageInvalidate——主要调用handlePageFlip()函数,该函数主要是从各Layer对应的BufferQueue中拿图形缓冲区数据,并根据内容更新脏区域。

handleMessageRefresh——合并和渲染输出。

合并渲染完成后,该线程继续等待下一个invalidate消息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值