什么是输入事件?
我们知道,运行android系统的设备本质上是一台计算机,使用者在和计算机进行交互的时候可以抽象成简单的对计算机的输入和输出(IO)。那么对于运行在计算机上的操作系统来说,操作系统在与使用者进行交互的时候起始也是可以抽象成对外界的输入进行处理,然后在输出返还给使用者。本文只讨论的是android系统中的“输入事件”(因为本文讨论的都是输入事件,所以以下简称“输入事件”为“事件”)相关的内容。
根据以上描述,我们就可以回答上面的问题了:
事件是计算机设备接收到的输入信息。
有了以上的定义,我们先来研究下事件是怎么产生的?
在Android开发
系统中,事件是由用户的动作触发的,进而在android硬件层引起硬件状态的变化,android底层会将硬件的状态的变化封装成更加高级的类对象并传递到android 的Framework层,Framework会继续把事件传递给应用层(确切地说是应用层里面应用开发者编写的具体的View的子类对象),最终应用层层会根据事件来进行响应并将响应结果通过对硬件的调用反馈给用户。在以上的整个过程中,应用开发者只需要关注其中的一小部分就可以了,那就是事件从Framework层传递到应用层之后我们该怎么处理这些事件。当然,本文也主要讨论这些内容。
借用以下android 架构图来展示下事件从底层到应用层经历了多少过程。android架构图
注意:事件的传递并不是只传递一个单一的事件的,每一次用户的动作都会产生一个有序的事件列表,这个有序的事件列会被按顺序一次传递到应用层。
输入事件类型
android中所有的事件被抽象成了一个Java类,InputEvent。它有两个直接子类,MotionEvent和 KeyEvent,分别代表了动作事件(通常由触摸屏所产生,也是最常见的)的事件和按键所产生的事件。但是事实上InputEvent不止有这两种。因为android系统可运行的设备类型非常丰富,在不同的设备上对应不同的硬件,肯定也就回有不同的输入事件了,InputEvent按照事件的输入来源不同可以分为以下几类(非全部):
Sensor InputEvent(传感器输入事件)
Hook InputEvent(耳机Hook键输入事件)
On InputEvent(开机键输入事件)
Touch Screen InputEvent(触摸屏输入事件,也是本文主要介绍的)
Key InputEvent(按键输入事件,Home/Menu/Back,电视遥控器按键等)
Hover InputEvent(鼠标动作输入事件)
一般来说,android系统的运行设备是手机或者平板电脑,它们都会有触摸屏,最常见的输入事件还是Touch Screen InputEvent了。本文将会主要介绍TouchScreen InputEvent 和 Key InputEvent。android系统的输入设备列表参考这里:输入设备
Touch Screen InputEvent的处理和传递
Touch Screen InputEvent基础
Touch Screen InputEvent被封装成了一个java类-MotionEvent,它包含三个基础的事件,其它的事件都是在者三个事件的基础之上进行组合封装而成的,例如,click事件就是一个ACTION_DOWN 和一个 ACTION_UP的组合。
基础事件:
ACTION_DOWN 手指按到屏幕上
ACTION_MOVE 手指在屏幕上移动
ACTION_UP 手指从屏幕上离开
事件序列:
上文以及提到过,Touch Screen的事件并不是单个出现的,用户的每次交互都会产生一个事件序列,这个序列会以一个ACTION_DOWN开头,中间有0 或者 n个ACTION_MOVE事件,最后以一个ACTION_UP结尾。一个事件序列往往可以组成更加高级的事件,比如说点击事件、双击事件、手势事件等,View在消费这些事件的时候也会以一个独立的事件序列作为一个最小单位来消费,而不是一个个的基础事件。
所以,我们可以认识到,Touch Screen的事件是可以分为两种类型的:
基础类型:包含ACTION_DOWN、ACTION_MOVE、ACTION_UP三个。
复合类型:由基础类型的事件序列组合称一个代表了用户特定的输入信息的事件。
几个关键方法及其其作用
在软件开发中,当我们写下一个方法后,我们的目的可能是使用该方法完成某些功能,也有可能是为了程序的可扩展性等其它的理由。打个比方来说,在android的常用组件Activity类中,有一个方法叫做setContentView(),它的作用是给当前的Activity指定一个布局来显示,这样的方法就是我们刚提到的“来完成某些功能”的方法;Activity中还有一个叫做onCreate() 的方法,它的作用是一个占位的方法,表示现在是Activity正在创建的时机,可以在子类来重写该方法完成一些初始化工作,像这类方法并没有完成某些具体的功能,就是我们提到的“为了程序的可扩展性等其它的理由”。为了方便起见,在本文中我将会称第一种方法为“功能型方法”,称第二种为“结构型方法”。但是有些方法并不是简单地确认为某一种类型,它可能两种特性都包含。还以以上提到的Activity的onCreate方法为例,首先,它是个结构型方法,因为它的目的包括通知子类进行初始化工作,其次,它本身也进行了一部分对Activity的初始化,这样来说,他就也完成了某些功能,也可以说是一个功能型方法,事实上onCreate两者都是(以下简称该类方法为Both)。
在MotionEvent的处理和传递过程中有几个关键的方法,他们分别出现咋View、ViewGroup、Activity、Window等多个类中,但是名字则是完全一致,功能也是非常接近的。
以上提到了几个关键方法是MotionEvent事件分发和处理的关键所在,它们涉及到几个类:
Activity
Window
View
ViewGroup
那么,MotionEvent事件是如何在这几个类之间传递的呢?而且我们以及知道了事件是由Framework层传递到应用层的,那么究竟是谁从Framework层传递过来,又是谁在应用层接收到了呢?
通过查看android SDK的源码,可以发现是WindowManagerService这个关键类把事件从Framework层传递到应用层的,并且通过PhoneWindow的成员DecorView传递到了当前的Activity中(具体详情请参考Android FrameWork——Touch事件派发过程详解,本文不再赘述)。也就是说是WindowManagerService做了Framework层和应用层的桥梁,把MotionEvent事件传递给了当前的Activity,当前Activity是应用层最先接收到MotionEvent事件的类。
这时候,就可以理解为什么在Activity中有dispatchTouchEvent 和 onTouchEvent这两个类了,因为Activity是应用层事件分发的第一站。
我们已经了解到了MotionEvent是怎么通过Activity传递到View中的,而android的View层是一个拥有树状结构的View树,树的每一个节点也都是一个View,那么MotionEvent是怎么在View树内部传递的呢?
首先,与该事件相关的根View的dispatchTouchEvent会被调用,一次来在该View内分发事件,事件会被分发给该类的onTouchEvent方法、该View的OnTouchListener的onTouch方法、以及子View的dispatchTouchEvent方法。View会依据以上所提到的三个目标方法的返回值来觉得dispatchTouchEvent的最终返回值。
然后,当事件被分发到onTouchEvent方法中以后,该View会对事件进行处理,View的OnClickListener的onClick方法便是在这里调用的。
假如说该View是一个ViewGroup,那么它的onInterceptTouchEvent方法会在dispatchTouchEvent方法执行的时候被调用,并根据是否打断事件传递来觉得dispatchTouchEvent的返回值。
以下伪代码可以清晰地展示它们三者的关系:
Java
public booleandispatchTouchEvent(MontionEvent e){
boolean consume = false;
if(onInterceptTouchEvent(e)){
consume = onTouchEvent(e);
}else{
consume = child.dispatchTouchEvent(e);
}
return consume;
}
public booleandispatchTouchEvent(MontionEvent e){
boolean consume = false;
if(onInterceptTouchEvent(e)){
consume = onTouchEvent(e);
}else{
consume = child.dispatchTouchEvent(e);
}
return consume;
}
当然,事实上View中的dispatchTouchEvent要复杂的多,它需要处理的东西非常多,这里我们就只挑主要的介绍了。
MotionEvent事件序列是被当做一个整体来处理的,假如一个View不消耗一个ACTION_DOWN事件,那么随后的其它该序列的事件也将不会传递给它。
当一个View觉得要处理某个时间序列的话,该事件序列的所有子事件都将会被交给它处理。
ViewGroup的onInterceptTouchEvent默认返回false,也就是说ViewGroup默认是不拦截事件的。
Key InputEvent的处理和传递
Key InputEvent 基础
在应用层,Key InputEvent被封装成了一个叫做KeyEvent的类,它想MotionEvent一样,也是InputEvent的一个子类。总的来说,KeyEvent在应用层的传递方式和Motion Event是一致的。都是由WindowManagerService获取到事件,由DecorView调用ViewRoot,进而按照Activity-Window-View树的流程传递事件的。
类似于MotionEvent的关键方法,KeyEvent的关键方法分别是:
dispatchKeyEvent
onKeyEvent
onInterceptKeyEvent
在View树中的传递过程与Touch事件的一致,这里不再赘述。
以上所提到的只是Android开发
中事件分发机制的大致轮廓,具体的代码则要复杂的多,大家有时间的话可以研究下具体的源码,相信大家都会有很大的收获的。
分享到:
相关推荐
1. **WindowManagerService**:作为系统级的服务,负责接收来自硬件的原始输入事件并将其分发给对应的窗口。 2. **ViewRootImpl**:它是View的根节点,负责接收来自WindowManagerService的事件,并向下传递给具体的...
### Android事件分发机制详解 #### 一、触摸事件涉及的核心类 在Android系统中,触摸事件主要由两类核心对象负责处理:`ViewGroup` 和 `View`。 1. **ViewGroup**:作为容器,继承自 `View`,用于容纳多个 `View`...
在深入探讨Android输入事件流程之前,我们先来了解其核心概念。Android系统通过一套复杂的机制处理各种输入事件,包括触摸、按键等,这一过程涉及多个组件和服务,确保用户输入能够被准确捕捉并适当地传递到应用层。...
在Android系统中,输入事件处理是用户界面交互的关键部分,涉及了从硬件设备到应用程序的事件传递过程。本文将深入探讨Android编程中的输入事件流程,包括事件的产生、捕获和分发机制。 首先,输入事件始于硬件设备...
Android输入子系统的核心在于如何高效且准确地处理各种类型的输入事件,并将它们转换成应用程序可以理解和处理的形式。通过对`KeyInputQueue`服务的分析可以看出,Android系统通过一系列精心设计的数据结构和处理...
在Android系统中,事件处理主要包括触摸事件、键盘事件、广播事件等,这些事件的处理方式直接影响到应用的用户体验和功能实现。下面我们将深入探讨Android事件处理机制的原理及其源码分析。 首先,Android事件处理...
Android事件分发分为三个步骤:dispatchTouchEvent、onInterceptTouchEvent和onTouchEvent。 1. dispatchTouchEvent:事件首先由根ViewGroup接收到,然后向下分发。每个ViewGroup都有机会拦截或传递事件。 2. ...
它不仅管理着各类输入设备的驱动,还负责将硬件事件转化为Android系统能理解的格式,确保输入事件的正确分发和处理。理解input子系统的架构和工作原理对于Android系统的优化和设备驱动的开发具有重要意义。
`input_dev`结构是Android输入子系统中的关键数据结构之一,用于描述一个输入设备的基本属性和能力。以下是对`input_dev`结构的部分字段进行解释: - `void *private;`: 用户可以自定义的数据指针。 - `const char ...
Android UI详解文档主要涵盖的是Android操作系统用户界面的设计与开发相关知识。在Android平台上,开发者可以利用丰富的组件和设计工具创建出美观且功能丰富的应用程序。以下是对Android UI系统深入讲解的一些关键...
在Android系统中,KeyEvent是处理用户输入硬件按键事件的关键类,它封装了按键按下和释放的动作。本资料主要探讨在Android 9.0 (Pie) 和 Android 10.0 (Q) 操作系统版本中,在framework层添加KeyEvent事件的详细流程...
这些组件协同工作,确保从硬件设备接收到的输入事件能够正确地被系统解析并分发给相应的应用。 1. **EventHub**: EventHub是Android框架层的起点,它负责从Linux内核接收并处理所有的输入事件,包括按键和触摸...
- **概述**:负责处理与图形窗口相关的事件,包括输入事件的分发、窗口的绘制等。 - **基本原理**:GWES的核心组件包括Window Manager、Input Manager等,它们协同工作以实现高效的窗口管理和输入事件处理。 6. *...
总结,InputChannel是Android系统中处理输入事件的关键组件,它连接着Native层与Dalvik虚拟机,实现了输入事件的高效、准确分发。了解InputChannel的工作原理,对于开发者优化应用的交互体验、解决输入问题至关重要...
### Android各组件详解 #### 一、Android简介 Android是一个基于Linux内核的开源操作系统,最初由Andy Rubin创建,后来被Google收购,并于2007年11月5日正式对外公布。Android的设计目的是为了适应现代移动设备的...
输入子系统有一个事件分发机制,它会根据事件的类型和优先级,将事件分发给相应的应用程序或操作系统服务。例如,键盘事件通常被分发给当前有焦点的应用程序,而鼠标事件可能会影响到窗口管理器的布局和行为。这个...
Android系统支持OpenGL ES(Embedded Systems版本的OpenGL),这是一个用于绘制2D和3D图形的标准API。对于3D游戏开发,通常使用OpenGL ES 2.0或更高版本,因为它们提供了着色器语言(GLSL),允许开发者自定义顶点和...
本资料“Android 3D游戏开发技术详解与典型案例PDF1-14章”涵盖了这些关键领域,帮助开发者深入理解和掌握Android 3D游戏的开发流程。 首先,从标题中我们可以推断出,这份资料可能包含14个章节,详细讲解了Android...
### Android事件处理详解:按键与触摸屏事件 #### 一、概述 在Android系统中,事件处理机制是用户界面交互的基础。本篇文章将重点探讨按键和触摸屏事件的处理过程,包括事件的生成、传递以及最终如何被应用程序所...
【Android聊天系统代码详解】 本项目提供了一个简易的聊天系统,涵盖了客户端与服务器的实现,主要功能包括聊天、文件传输以及好友管理。整个系统基于Java编程语言,运行在Android平台上,是初学者学习Android开发...