Android系列之 屏幕触控机制(一)

目录

[1 Android native层传递点击事件](#1 Android native层传递点击事件)

[2 .Window和WindowManagerService的关系](#2 .Window和WindowManagerService的关系)

[2.1 ViewRootImpl 如何串联Window和WindowManagerService](#2.1 ViewRootImpl 如何串联Window和WindowManagerService)

[2.2 ViewRootImpl和Window的关系](#2.2 ViewRootImpl和Window的关系)

[2.3 ViewRootImpl和WindowManagerService的关系](#2.3 ViewRootImpl和WindowManagerService的关系)


以下章节待分解:

  1. ViewRootImpl的事件接收及分发

  2. ViewGroup事件的分发机制

4.1 activity的视图创建流程

4.2 ViewGroup的事件分发流程

4.3 View的事件处理

  1. 事件分发具体案例及解决方案

Android屏幕触控机制整体流程图

图1

1 Android native层传递点击事件

当用户点击屏幕时,屏幕会产生触摸事件,Linux内核会将触摸事件封装成event存到/dev/input/文件内。

inputReader从EventHub读取到事件并发送给InputDispatcher,

InputDispatcher分发至framework层 需要处理的地方。

下面我们来详细看一下framework层是如何接收点击事件并最终如何响应点击事件的

图2

2 .Window和WindowManagerService的关系

图3

2.1 ViewRootImpl 如何串联Window和WindowManagerService

当一个点击事件从native传递到framework时,viewRootImpl中的WindowInputEventReceiver()方法会最先响应点击事件。

而这个WindowInputEventReceiver()方法中的mInputChannel参数,是在WindowManagerService(以下简称wms )中和native层关联上的。

这个时候就有个疑问了,点击事件怎么和wms有关联了呢?其实wms他是一个重要的系统服务,用于窗口管理,他就是窗口的大主管,因为它记录了当前系统中所有窗口的完整信息,他还是点击事件的派发者,所以只有它才能判断出要把点击的事件投递给具体的某个应用进程进行处理。而应用进程如何接收的了?这里的应用进程可以理解成是一个应用层级的窗口Window。因为事件点击的目的地是应用层级的窗口Window。而wms和window中间需要一个纽带去衔接,这个中间的纽带就是ViewRootImpl, ViewRootImpl负责view 的绘制,也负责用户的点击操作处理。

下面就讲一下viewRootImp是如何创建并成为window和wms的纽带的。

2.2 ViewRootImpl和Window的关系

说起ViewRootImpl和window的关系,就要先看一下 ViewRootImpl是在哪里被创建的 ,这就要从handleResumeActivity流程开始看起

java 复制代码
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,String reason) {
        ......
    if (r.window == null && !a.mFinished && willBeVisible) {
        ......
    View decor = r.window.getDecorView();
        ......
    ViewManager wm = a.getWindowManager();
        ......
    wm.addView(decor, l);
        ......
}

wm.addView的wm的实例对象就是WindowManagerImpl,其中的参数decor是DecorView对象

接着看WindowManagerImpl的addView方法做了什么

java 复制代码
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyDefaultToken(params);
    mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}

又调用到了 WindowManagerGlobal的addView方法,可以看到ViewRootImpl在这里被创建了,并绑定了DecorView

java 复制代码
public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
        ......
        root = new ViewRootImpl(view.getContext(), display);
         ......
        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);
        root.setView(view, wparams, panelParentView);
        ......
}

2.2 ViewRootImpl和Window的关系

流程图大致介绍了ViewRootImpl是如何创建出来的,总结一下:在ActivityThread的handleResumeActivity()流程中,通过

WindowManager(WindowManagerImpl)的 addView() 实现了ViewRootImpl的创建。 此时我们应用层窗口Window就和ViewRootImpl建立了关联。

图4

2.3 ViewRootImpl和WindowManagerService的关系

而ViewRootImpl和wms的关联,是在ViewRootImpl的setview方法中

mWindowSession.addToDisplay()函数是添加窗口流程,对应的服务端就是WMS,而WMS又是个系统进程,所以这是个Binder跨进程调用方法,最终调用的是WMS的addWindow方法。而参数mInputChannel,它包括了发送和接收消息的功能封装。

最后声明了inputEvent方法,用来接受从底层传过来的点击事件

java 复制代码
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    synchronized (this) {
            ......

            requestLayout();
            if ((mWindowAttributes.inputFeatures
                    & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                mInputChannel = new InputChannel();
            }
            ......
            res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                        getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
                        mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                        mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
            ......

            if (mInputChannel != null) {

                    ... // 声明了inputEvent方法,用来接受从底层传过来的点击事件

                    mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
                            Looper.myLooper());
             }
}
相关推荐
消失的旧时光-194318 小时前
从 Kotlin 到 Dart:为什么 sealed 是处理「多种返回结果」的最佳方式?
android·开发语言·flutter·架构·kotlin·sealed
Jinkxs18 小时前
Gradle - 与Groovy/Kotlin DSL对比 构建脚本语言选择指南
android·开发语言·kotlin
&有梦想的咸鱼&18 小时前
Kotlin委托机制的底层实现深度解析(74)
android·开发语言·kotlin
LDORntKQH18 小时前
基于深度强化学习的混合动力汽车能量管理策略 1.利用DQN算法控制电池和发动机发电机组的功率分配 2
android
冬奇Lab18 小时前
Android 15 ServiceManager与Binder服务注册深度解析
android·源码·源码阅读
2501_9160088920 小时前
深入解析iOS机审4.3原理与混淆实战方法
android·java·开发语言·ios·小程序·uni-app·iphone
独行soc1 天前
2026年渗透测试面试题总结-20(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
常利兵1 天前
2026年,Android开发已死?不,它正迎来黄金时代!
android
Risehuxyc1 天前
备份三个PHP程序
android·开发语言·php
Doro再努力1 天前
【Linux操作系统10】Makefile深度解析:从依赖推导到有效编译
android·linux·运维·服务器·编辑器·vim