【易客吧】_全网激活码总代_激活码商城

您现在的位置是:首页 > 热门资讯 > 正文

热门资讯

Android 事件分发机制详解:从源头到事件处理的综合指南 (android是什么)

用户投稿2024-04-19热门资讯20

简介

Android 事件分发机制是 Android 系统中关键且复杂的一个系统,它负责处理来自用户界面的事件,并将其传递给适当的组件进行处理。本文旨在提供有关 Android 事件分发机制的全面指南,从事件源头到事件处理的整个过程。

事件分发流程

Android 事件分发是一个多阶段的过程,涉及以下主要步骤:1. 事件源:用户交互或系统事件会生成一个事件对象。 2. 事件传递:事件在组件层次结构中从源头向下传递,直到找到可以处理事件的组件。 3. 事件处理:组件处理事件,执行用户操作或对事件进行响应。 4. 事件返回:如果需要,事件会沿组件层次结构返回到源头,以便其他组件可以执行额外的处理。

事件类型

Android 支持多种类型的事件,包括:触摸事件:来自触摸屏的事件,例如点击、滑动和长按。键盘事件:来自物理键盘或软键盘的事件,例如按键按下和释放。输入事件:与输入设备(如手写笔或轨迹球)交互的事件。系统事件:由系统生成的事件,例如系统启动和关闭。

事件源头

事件源头是生成事件的 UI 组件。最常见的事件源头是:视图:屏幕上可见的 UI 元素,例如按钮、文本框和列表。视图组:一个可以包含其他视图的容器,例如布局和片段。

事件传递

事件从源头向下的传递通过一系列回调方法进行,称为 onTouchEvent() onKeyDown() 等。每个组件都有机会拦截或处理事件,如果处理了事件,则传递将停止。传递的顺序取决于组件在视图层次结构中的位置。子视图先收到事件,然后是父视图,依此类推。

事件处理

当组件处理事件时,它执行用户操作或对事件进行响应。处理可以包括:更新 UI(例如,更改按钮的颜色)。执行操作(例如,启动新的活动)。将事件转发给其他组件。

事件返回

处理完事件后,事件会沿组件层次结构返回到源头。这允许其他组件执行额外的处理,例如拦截返回键并阻止其退出活动。

事件分发拦截

事件分发可以被组件拦截,以便在将事件传递给子组件之前处理它。拦截可以通过覆写 onInterceptTouchEv}returntrue;} }

最佳实践

优化事件处理:使用轻量级的事件监听器和避免不必要的事件分发拦截。正确处理触摸事件:使用适当的触摸事件类型和检测手势。考虑事件优先级:根据组件的预期行为设置正确的事件优先级。使用 touch delegate:允许组件接收超出其边界之外的触摸事件。理解事件分发生命周期:了解事件在组件层次结构中的传递和返回过程。

结论

Android 事件分发机制是 Android 系统的核心部分,它提供了处理用户交互和系统事件的健壮且灵活的方式。通过了解其工作原理和最佳实践,您可以创建高效且响应迅速的 Android 应用程序。

Android Touch事件分发处理机制详解

Android应用的开发过程不可能不涉及到Touch事件的处理,简单地如设置OnClickListener、OnLongClickListener等监听器处理View的点击事件,复杂地如在自定义View中通过重写onTouchEvent来捕获用户交互事件以定制出各种效果,在使用的过程中或多或少会遇到一些奇怪的Bug,让你对Touch事件“从哪来,到哪去”产生迷之疑惑,经过多少次徘徊之后终于决定系统的分析下源码,本文就给大家分享下我的收获。

MotionEvent作为Touch事件的载体,采用时间片来管理Touch事件所有相关行为的数据,本文这样理解时间片这个概念:

通常MotionEvent会将触发当前事件的Pointer作为主要Pointer,其PointerIndex为0,而MotionEvent通过提供getX()这类不带index参数的接口以更方便的操作主要Pointer的数据。 了解了MotionEvent的组成结构之后,接下来就可以分析MotionEvent包含的事件类型了,MotionEvent通过getAction接口来获取事件Action,而Action中低8位地址存储的是事件类型(对于触摸事件来说,主要包括Down、Move、Up、Cancel、PointerDown、PointerUp),高8位地址存储的是PointerId(当事件类型为PointerDown、PointerUp时)。通常来说事件会以Down开始,以Up或Cancel结束,各事件所承担的角色以及各自的特点在分析事件分发与处理的过程时再详细说明。 另外,MotionEvent中的Flag需要说明一下:

本文仅分析Touch事件在Framework中Java层的传递,因此从事件传递到Activity开始分析。当Touch事件传递给Activity时,会调用(MotionEvent),Activity会将事件传递给其Window进行处理,实际会调用(MotionEvent),PhoneWindow会将该事件传递给Android中View层级中的顶层View(即DecorView)进行处理:

在Window未设置Callback的情况下,会调用父类的dispatchTouchEvent,DecorView继承自FrameLayout,然后FrameLayout并未实现dispatchEvent,因此最终调用,也就是Touch事件分发的核心逻辑所在,前文中提到MotionEvent中事件类型主要包括Down、Move、Up、Cancel、PointerDown、PointerUp,而dispatchTouchEvent根据事件的不同类型会做不同处理,因此这里分别进行分析:

Down事件处理

非异常情况下,Touch事件的事件周期总是以Down事件开始的,因此Down事件在整个事件分发逻辑中起关键作用,将决定了后续Move、Up及Cancel事件的处理主体,先看一张Down事件分发的流程图:

从流程图中可以看到,Down事件的分发逻辑主要目的在于寻找到能处理该Touch事件的View控件(该View为以当前ViewGroup为Root节点的View层级中的View,利用寻找到的View创建事件处理Target),整个处理逻辑主要包含以下几步:

Move、Up、Cancel事件处理

完成Down事件的分发逻辑后,就确定了该Down事件后续Move、Up及Cancel事件的处理主体(注意:这里并没有确定PointerDown事件的处理主体,关于PointerDown事件的分发逻辑稍后分析),先通过一张流程图来感受下Move、Up、Cancel事件的分发逻辑:

从流程图可以看出,对于Move、Up、Cancel事件的分发步骤如下:

PointerDown事件处理

PointerDown事件是在支持多Pointer(调用setMotionEventSplittingEnabled将FLAG_SPLIT_MOTION_EVENTS置位)的环境下,当有新的Pointer按下时产生的,该事件处理的特殊性在于会重新遍历View层级,寻找可以处理新Pointer事件的Target,具体流程参考Down事件的分发逻辑;遍历结束若仍没有找到处理该事件的Target,则会将新Pointer的处理权设置给已有Target中最早被添加的Target。完成Target的寻找之后,会将该事件通过dispatchTransformedTouchEvent传递至所有已有Target进行处理,可以通过下面流程图,对PointerDown事件的处理有一个更全局的认识:

PointerUp事件处理

相对于Up事件来说,对于PointerUp事件的处理区别在于当传递至所有已有Target结束之后并不能标记以Down事件起始的整个事件周期结束,仅能标记其关联Pointer(以PointerDown事件起始)的事件周期结束,因此不会清除所有状态,而仅会从已有Target中移除掉与该Pointer相关的部分。

onInterceptTouchEvent

在ViewGroup进行事件分发的过程中,会调用该函数来确定是否需要拦截事件,当该函数返回true时该事件将会被拦截,即不会进行正常的View层级传递,而是直接由该ViewGroup来处理,而拦截后的操作需要根据拦截事件的类型不同而不同:

dispatchTransformedTouchEvent(MotionEvent event, boolean cancel, View child, int desiredPointerIdBits)

在将事件传递给Target进行处理之前会调用该函数对MotionEvent进行处理:

(int idBits)

判断一个View控件是否消费一个事件,是由的返回值来决定的,而用于寻找事件的最终消费者,话不多说,还是通过一张流程图来个直观感受:

从流程图中可以看出,View会根据ouch事件对Scroll状态进行调整,并寻找该事件的最终处理器:

将向其直接ViewGroup返回是否消费掉该事件,返回值将决定上级ViewGroup是否需要继续询问其他子View是否需要消费该事件。这就是View中分发事件的逻辑,真是简单粗暴!

从的分析中可以发现当未对View设置mTouchListener或mTouchListener未消费掉该事件时,Touch事件最终将由来决定是否消费,自定义View可以重写该方法实现自身的逻辑,此处仅分析View中的通用处理逻辑:

从上述分析可以很开心地发现熟悉的onClick及onLongClick事件的产生逻辑,若是之前没看过类似的文章,应该会有原来如此的感觉吧,哈哈~~

至此,Touch事件的分发与处理流程算是走通了,个人看完整个源码之后有种豁然开朗的感觉,能很清晰的分析向“为什么事件有时候传到某个View有时候却不传?”、“有时候只传前面几个事件后面却不传了?”等问题,也希望本文的分析能让你更清晰地感知Android中Touch事件的传递流程,如果发现文中有何错误,希望不吝赐教!

android事件分发机制 什么意思

android事件分发机制 就是一个触摸事件发生了,从一个窗口传递到一个视图,再传递到另外一个视图,最后被消费的过程,在android中还是比较复杂的传递流程如下:(1) 事件从()开始传递,只要没有被停止或拦截,从最上层的View(ViewGroup)开始一直往下(子View)传递。 子View可以通过onTouchEvent()对事件进行处理。 (2) 事件由父View(ViewGroup)传递给子View,ViewGroup可以通过onInterceptTouchEvent()对事件做拦截,停止其往下传递。 (3) 如果事件从上往下传递过程中一直没有被停止,且最底层子View没有消费事件,事件会反向往上传递,这时父View(ViewGroup)可以进行消费,如果还是没有被消费的话,最后会到Activity的onTouchEvent()函数。 (4) 如果View没有对ACTION_DOWN进行消费,之后的其他事件不会传递过来。 (5) OnTouchListener优先于onTouchEvent()对事件进行消费。 上面的消费即表示相应函数返回值为true。

请简述什么是android事件处理,并分析两种android事件处理机制的实现过程和区别

UI编程通常都会伴随事件处理,Android也不例外,它提供了两种方式的事件处理:基于回调的事件处理和基于监听器的事件处理。

对于基于监听器的事件处理而言,主要就是为Android界面组件绑定特定的事件监听器;对于基于回调的事件处理而言,主要做法是重写Android组件特定的回调函数,Android大部分界面组件都提供了事件响应的回调函数,我们主要重写它们就行。

一 基于监听器的事件处理

相比于基于回调的事件处理,这是更具“面向对象”性质的事件处理方式。在监听器模型中,主要涉及三类对象:

2)事件Event:事件封装了界面组件上发生的特定事件的具体信息,如果监听器需要获取界面组件上所发生事件的相关信息,一般通过事件Event对象来传递。

3)事件监听器Event Listener:负责监听事件源发生的事件,并对不同的事件做相应的处理。

基于监听器的事件处理机制是一种委派式Delegation的事件处理方式,事件源将整个事件委托给事件监听器,由监听器对事件进行响应处理。这种处理方式将事件源和事件监听器分离,有利于提供程序的可维护性。

举例:

View类中的OnLongClickListener监听器定义如下:(不需要传递事件)

[java] view plaincopyprint?

public interface OnLongClickListener {

boolean onLongClick(View v);

public interface OnLongClickListener {boolean onLongClick(View v);}

View类中的OnLongClickListener监听器定义如下:(需要传递事件MotionEvent)

[java] view plaincopyprint?

public interface OnTouchListener {

boolean onTouch(View v, MotionEvent event);

Android 事件分发机制详解:从源头到事件处理的综合指南 (android是什么) 第1张

public interface OnTouchListener {boolean onTouch(View v, MotionEvent event);}

二 基于回调的事件处理

相比基于监听器的事件处理模型,基于回调的事件处理模型要简单些,该模型中,事件源和事件监听器是合一的,也就是说没有独立的事件监听器存在。当用户在GUI组件上触发某事件时,由该组件自身特定的函数负责处理该事件。通常通过重写Override组件类的事件处理函数实现事件的处理。

举例:

View类实现了接口中的一系列回调函数,因此,基于回调的事件处理机制通过自定义View来实现,自定义View时重写这些事件处理方法即可。

[java] view plaincopyprint?

public interface Callback {

// 几乎所有基于回调的事件处理函数都会返回一个boolean类型值,该返回值用于

// 标识该处理函数是否能完全处理该事件

// 返回true,表明该函数已完全处理该事件,该事件不会传播出去

// 返回false,表明该函数未完全处理该事件,该事件会传播出去

boolean onKeyDown(int keyCode, KeyEvent event);

boolean onKeyLongPress(int keyCode, KeyEvent event);

boolean onKeyUp(int keyCode, KeyEvent event);

boolean onKeyMultiple(int keyCode, int count, KeyEvent event);

public interface Callback { // 几乎所有基于回调的事件处理函数都会返回一个boolean类型值,该返回值用于 // 标识该处理函数是否能完全处理该事件// 返回true,表明该函数已完全处理该事件,该事件不会传播出去// 返回false,表明该函数未完全处理该事件,该事件会传播出去boolean onKeyDown(int keyCode, KeyEvent event);boolean onKeyLongPress(int keyCode, KeyEvent event);boolean onKeyUp(int keyCode, KeyEvent event);boolean onKeyMultiple(int keyCode, int count, KeyEvent event);}

三 比对

基于监听器的事件模型符合单一职责原则,事件源和事件监听器分开实现;

Android的事件处理机制保证基于监听器的事件处理会优先于基于回调的事件处理被触发;

某些特定情况下,基于回调的事件处理机制会更好的提高程序的内聚性。

四 基于自定义监听器的事件处理流程

在实际项目开发中,我们经常需要自定义监听器来实现自定义业务流程的处理,而且一般都不是基于GUI界面作为事件源的。这里以常见的app自动更新为例进行说明,在自动更新过程中,会存在两个状态:下载中和下载完成,而我们的程序需要在这两个状态做不同的事情,“下载中”需要在UI界面上实时显示软件包下载的进度,“下载完成”后,取消进度条的显示。这里进行一个模拟,重点在说明自定义监听器的事件处理流程。

4.1)定义事件监听器如下:

若对本页面资源感兴趣,请点击下方或右方图片,注册登录后

搜索本页相关的【资源名】【软件名】【功能词】或有关的关键词,即可找到您想要的资源

如有其他疑问,请咨询右下角【在线客服】,谢谢支持!

Android 事件分发机制详解:从源头到事件处理的综合指南 (android是什么) 第2张

发表评论

评论列表

  • 这篇文章还没有收到评论,赶紧来抢沙发吧~
欢迎你第一次访问网站!