导航:首页 > 操作系统 > android事件处理机制

android事件处理机制

发布时间:2023-01-04 08:00:16

android 系统运行机制 【Looper】【Choreographer】篇

目录:
1 MessageQueue next()
2 Vsync
3 Choreographer doFrame
4 input

系统是一个无限循环的模型, Android也不例外,进程被创建后就陷入了无限循环的状态

系统运行最重要的两个概念:输入,输出。

Android 中输入 输出 的往复循环都是在 looper 中消息机制驱动下完成的

looper 的循环中, messageQueue next 取消息进行处理, 处理输入事件, 进行输出, 完成和用户交互

应用生命周期内会不断 产生 message 到 messageQueue 中, 有: java层 也有 native层

其中最核心的方法就是 messageQueue 的 next 方法, 其中会先处理 java 层消息, 当 java 层没有消息时候, 会执行 nativePollOnce 来处理 native 的消息 以及监听 fd 各种事件

从硬件来看, 屏幕不会一直刷新, 屏幕的刷新只需要符合人眼的视觉停留机制

24Hz , 连续刷新每一帧, 人眼就会认为画面是流畅的

所以我们只需要配合上这个频率, 在需要更新 UI 的时候执行绘制操作

如何以这个频率进行绘制每一帧: Android 的方案是 Vsync 信号驱动。

Vsync 信号的频率就是 24Hz , 也就是每隔 16.6667 ms 发送一次 Vsync 信号提示系统合成一帧。

监听屏幕刷新来发送 Vsync 信号的能力,应用层 是做不到的, 系统是通过 jni 回调到 Choreographer 中的 Vsync 监听, 将这个重要信号从 native 传递到 java 层。

总体来说 输入事件获取 Vsync信号获取 都是先由 native 捕获事件 然后 jni 到 java 层实现业务逻辑

执行的是 messageQueue 中的关键方法: next

next 主要的逻辑分为: java 部分 和 native 部分

java 上主要是取java层的 messageQueue msg 执行, 无 msg 就 idleHandler

java层 无 msg 会执行 native 的 pollOnce@Looper

native looper 中 fd 监听封装为 requestQueue, epoll_wait 将 fd 中的事件和对应 request 封装为 response 处理, 处理的时候会调用 fd 对应的 callback 的 handleEvent

native 层 pollOnce 主要做的事情是:

vsync 信号,输入事件, 都是通过这样的机制完成的。

epoll_wait 机制 拿到的 event , 都在 response pollOnce pollInner 处理了

这里的 dispatchVsync 从 native 回到 java 层

native:

java:

收到 Vsync 信号后, Choreographer 执行 doFrame

应用层重要的工作几乎都在 doFrame 中

首先看下 doFrame 执行了什么:

UI 线程的核心工作就在这几个方法中:

上述执行 callback 的过程就对应了图片中 依次处理 input animation traversal 这几个关键过程

执行的周期是 16.6ms, 实际可能因为一些 delay 造成一些延迟、丢帧

input 事件的整体逻辑和 vsync 类似

native handleEvent ,在 NativeInputEventReceiver 中处理事件, 区分不同事件会通过 JNI

走到 java 层,WindowInputEventReceiver 然后进行分发消费

native :

java:

input事件的处理流程:

输入event deliverInputEvent

deliver的 input 事件会来到 InputStage

InputStage 是一个责任链, 会分发消费这些 InputEvent

下面以滑动一下 recyclerView 为例子, 整体逻辑如下:

vsync 信号到来, 执行 doFrame,执行到 input 阶段

touchEvent 消费, recyclerView layout 一些 ViewHolder

scroll 中 fill 结束,会执行 一个 recyclerView viewProperty 变化, 触发了invalidate

invalidate 会走硬件加速, 一直到达 ViewRootImpl , 从而将 Traversal 的 callback post choreographer执行到 traversal 阶段就会执行

ViewRootImpl 执行 performTraversal , 会根据目前是否需要重新layout , 然后执行layout, draw 等流程

整个 input 到 traversal 结束,硬件绘制后, sync 任务到 GPU , 然后合成一帧。

交给 SurfaceFlinger 来显示。

SurfaceFlinger 是系统进程, 每一个应用进程是一个 client 端, 通过 IPC 机制,client 将图像显示工作交给 SurfaceFlinger

launch 一个 app:

Ⅱ Android View 事件分发机制

Android 事件机制包含系统启动流程、输入管理(InputManager)、系统服务和 UI 的通信(WindowManagerService + ViewRootImpl + Window)、事件分发等一系列的环节。

Android 系统中将输入事件定义为 InputEvent,根据输入事件的类型又分为了 KeyEvent(键盘事件) 和 MotionEvent(屏幕触摸事件)。这些事件统一由系统输入管理器 InputManager 进行分发。

在系统启动的时候,SystemServer 会启动 WindowManagerService,WMS 在启动的时候通过 InputManager 来负责监控键盘消息。

InputManager 负责从硬件接收输入事件,并将事件通过 ViewRootImpl 分发给当前激活的窗口处理,进而分发给 View。

Window 和 InputManagerService 之间通过 InputChannel 来通信,底层通过 socket 进行通信。

Android Touch 事件的基础知识:

KeyEvent 对应了键盘的输入事件;MotionEvent 就是手势事件,鼠标、笔、手指、轨迹球等相关输入设备的事件都属于 MotionEvent。

InputEvent 统一由 InputManager 进行分发,负责与硬件通信并接收输入事件。

system_server 进程启动时会创建 InputManagerService 服务。

system_server 进程启动时同时会启动 WMS,WMS 在启动的时候就会通过 IMS 启动 InputManager 来监控键盘消息。

App 端与服务端建立了双向通信之后,InputManager 就能够将产生的输入事件从底层硬件分发过来,Android 提供了 InputEventReceiver 类,以接收分发这些消息:

Window 和 IMS 之间通过 InputChannel 通信。InputChannel 是一个 pipe,底层通过 socket 进行通信。在 ViewRootImpl.setView() 过程中注册 InputChannel。

Android 事件传递机制是 先分发再处理 ,先由外部的 View 接收,然后依次传递给其内层的 View,再从最内层 View 反向依次向外层传递。

三个方法的关系如下:

分发事件:

应用了树的 深度优先搜索算法 (Depth-First-Search,简称 DFS 算法),每个 ViewGroup 都持有一个 mFirstTouchTarget, 当接收到 ACTION_DOWN 时,通过递归遍历找到 View 树中真正对事件进行消费的 Child,并保存在 mFirstTouchTarget 属性中,依此类推组成一个完整的分发链。在这之后,当接收到同一事件序列的其它事件如 ACTION_MOVE、ACTION_UP 时,则会跳过递归流程,将事件直接分发给下一级的 Child。

ViewGroup 分发事件的主要的任务是找一个 Target,并且用这个 Target 处理事件,主要逻辑如下 :

为什么倒序查找 TouchTarget?
如果按添加顺序遍历,当 View 重叠时(FrameLayout),先添加的 View 总是能消费事件,而后添加的 View 不可能获取到事件。

拦截事件:

[1] Android 事件分发机制的设计与实现
[2] Android 事件拦截机制的设计与实现

Ⅲ Android ANR 机制

广播的 ANR 处理相对简单,主要是再次判断是否超时、记录日志,记录 ANR 次数等。然后就继续调用 processNextBroadcast 函数,处理下一条广播了。

ContentProvider 超时为 CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10s

Activity 的 ANR 是相对最复杂的,也只有 Activity 中出现的 ANR 会弹出 ANR 提示框。
最终的表现形式是:弹出一个对话框,告诉用户当前某个程序无响应,输入一大堆与 ANR 相关的日志,便于开发者解决问题。

InputDispatching:

Activity 最主要的功能之一是交互,为了方便交互,Android 中的 InputDispatcher 会发出操作事件,最终在 InputManagerService 中发出事件,通过 InputChannel,向 Activity 分发事件。交互事件必须得到响应,如果不能及时处理,IMS 就会报出 ANR,交给 AMS 去弹出 ANR 提示框。

KeyDispatching:

如果输入是个 Key 事件,会从 IMS 进入 ActivityRecord.Token.keyDispatchingTimeOut,然后进入 AMS 处理,不同的是,在 ActivityRecord 中,会先截留一次 Key 的不响应,只有当 Key 连续第二次处理超时,才会弹出 ANR 提示框。

窗口焦点:

Activity 总是需要有一个当前窗口来响应事件的,但如果迟迟没有当前窗口(获得焦点),比如在 Activity 切换时,旧 Activity 已经 onPause,新的 Activity 一直没有 onResume,持续超过 5 秒,就会 ANR。
App 的生命周期太慢,或 CPU 资源不足,或 WMS 异常,都可能导致窗口焦点。

1. 判断是否有 focused 组件以及 focused Application:

这种一般是在应用启动时触发,比如启动时间过长在这过程中触发了 keyevent 或者 trackball moteionevent 就会出现。

对应于

2. 判断前面的事件是否及时完成:

对应于

出现这种问题意味着主线程正在执行其他的事件但是比较耗时导致输入事件无法及时处理。

InputDispatcher 超时是最常见的 ANR 类型,而且其类型也比较多。
当用户触摸屏幕或者按键操作,首次触发的是硬件驱动,驱动收到事件后,将该相应事件写入到输入设备节点, 这便产生了最原生态的内核事件。接着,输入系统取出原生态的事件,经过层层封装后成为 KeyEvent 或者 MotionEvent ;最后,交付给相应的目标窗口(Window)来消费该输入事件。可见,输入系统在整个过程起到承上启下的衔接作用。

Input 模块的主要组成:

每一个应用进程都会有一个 SignalCatcher 线程,专门处理 SIGQUIT,来到 art/runtime/signal_catcher.cc :

当应用发生 ANR 之后,系统会收集许多进程,来 mp 堆栈,从而生成 ANR Trace 文件。收集的第一个,也是一定会被收集到的进程,就是发生 ANR 的进程。接着系统开始向这些应用进程发送 SIGQUIT 信号,应用进程收到 SIGQUIT 后开始 mp 堆栈。

[1] developer ANRs
[2] Android ANR 分析详解
[3] 看完这篇 Android ANR 分析,就可以和面试官装逼了!
[4] 微信 Android 团队手把手教你高效监控 ANR
[5] Input 系统—ANR 原理分析 - Gityuan
[6] 彻底理解安卓应用无响应机制 - Gityuan
[7] 理解 Android ANR 的触发原理 - Gityuan

Ⅳ Android应用处理MotionEvent的过程

应用对于Motion事件的处理比较复杂,不同类型的事件处理方式不同:

下面从应用UI线程的 Looper 开始分析

下面看 NativeInputEventReceiver 的 handleEvent()

对于 InputEventReceiver 的 dispatchInputEvent() 处理流程,在后文中分析。

下面看 InputConsumer 的 consume() 实现

对于Down事件等直接处理的事件,处理过程相对简单,下面看Batch事件的处理过程。

下面从 NativeInputEventReceiver 的 consumeEvents() 开始分析。

对于Batch的首个Move事件,创建新的Batch,Move事件添加到Batch,然后循环读取,通常返回WOULD_BLOCK(无事件可读)。最终调用 WindowInputEventReceiver 的 () 。

下面看Vsync到来之前,Batch的后续Move事件的处理。

下面仍然从 NativeInputEventReceiver 的 consumeEvents() 开始分析

Batch的后续Move事件的处理相对简单,只是将Move事件添加到Batch,下面分析Vsync信号到来后,Batch事件的处理。

下面从App收到Vsync信号调用 CALLBACK_INPUT 类型的回调 ConsumeBatchedInputRunnable 开始分析。

下面看 consumeEvents() 的处理

无论直接处理还是Batch处理,最终都通过 WindowInputEventReceiver 的 dispatchInputEvent() 处理,下面分析该过程。

下面从 WindowInputEventReceiver 的 OnInputEvent() 开始分析

下面看 deliverInputEvent() 的实现

下面看 EarlyPostImeInputStage 的对 MotionEvent 的处理

EarlyPostImeInputStage 处理完事件后,传递给 NativePostImeInputStage 处理, NativePostImeInputStage 的处理过程非常简单,下面直接看 ViewPostImeInputStage 的处理。

至此,Motion事件已经传递给 Activity ,下面看Motion事件在 Activity 窗口内传递的过程。

下面从 Activity 的 dispatchTouchEvent() 开始分析

下面看 PhoneWindow 的 superDispatchTouchEvent() 的实现

下面分析 ViewGroup 的 dispatchTouchEvent() 实现

Ⅳ Android事件分发机制

Android中对视图的Touch事件进行分发处理。
单手指操作:ACTION_DOWN -> ACTION_MOVE -> ACTION_UP
多手指操作:ACTION_DOWN -> ACTION_POINTER_DOWN -> ACTION_MOVE -> ACTION_POINTER_UP -> ACTION_UP.

(1) dispatchTouchEvent() :事件分发

(2) onInterceptTouchEvent() :事件拦截

(3) onTouchEvent() :事件处理

ViewGroup 的相关事件有三个:onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent。

View 的相关事件只有两个:dispatchTouchEvent、onTouchEvent。

先分析ViewGroup的处理流程:首先得有个结构模型概念:ViewGroup和View组成了一棵树形结构,最顶层为Activity的ViewGroup,下面有若干的ViewGroup节点,每个节点之下又有若干的ViewGroup节点或者View节点,依次类推。如图:

点击事件达到顶级 View(一般是一个 ViewGroup),会调用 ViewGroup 的 dispatchTouchEvent 方法,如果顶级 ViewGroup 拦截事件即 onInterceptTouchEvent 返回 true,则事件由 ViewGroup 处理,这时如果 ViewGroup 的 mOnTouchListener 被设置,则 onTouch 会被调用,否则 onTouchEvent 会被调用。也就是说如果都提供的话,onTouch 会屏蔽掉 onTouchEvent。在 onTouchEvent 中,如果设置了 mOnClickListenser,则 onClick 会被调用。如果顶级 ViewGroup 不拦截事件,则事件会传递给它所在的点击事件链上的子 View,这时子 View 的 dispatchTouchEvent 会被调用。如此循环。

Ⅵ Framework事件机制——手撕Android事件处理的三种方法

Android的事件处理的三种方法:

setOnClickListener,setOnLongClickListener、setOnTouchListener

注意:如果onTouchEvent方法return true,则单击事件和长摁事件不再执行;若onLongClick方法返回true,则单击事件不再处理。

需要定义继承组件的类,重写回调方法Touch方法执行时,先被Activity捕获,DispatchTouchEvent方法处理。return false,交给上层的onTouchEvent方法处理;return super.dispatchTouchEvent(ev),则传递给最外层的View。

View用Dispatch方法处理,return false,由上层的onTouchEvent方法处理。如果返回super.dispatchTouchEvent(ev),则本层的onInterceptTouchEvent拦截,如果拦截true,则拦截,false不拦截,传递给子View的DispatchTouchEvent处理。

常用的回调方法:onKeyDown,onKeyLongPress,onKeyUp,onTouchEvent,onTrackballEvent(轨迹球事件)监听和回调同时存在时,先调用监听。

流程模型图:

Event source 事件源
Event 事件
Event Listener 事件监听器
下面我们来看一下点击事件和触摸事件的监听三要素具体是那部分:

由于点击事件比较简单,系统已经帮我们处理了,并没有找到具体事件是哪个。

View.OnClickListener 单击事件监听器必须实现的接⼝
View.OnCreateContextMenuListener 创建上下⽂菜单事件
View.OnFocusChangeListener 焦点改变事件
View.OnKeyListener 按键事件监听器
View.OnLongClickListener 长按事件监听器
View.OnTouchListener 触摸屏事件监听器

⾸先,事件监听机制中由事件源,事件,事件监听器三类对象组成。
事件监听器处理流程:

在此以OnClickListener单击事件为例使用intent来实现页面的跳转

监听事件处理是事件源与事件监听器分开的而基于回调的事件处理UI组件不但是事件源,而且还是事件监听器,通过组件的相关回调方法处理对应的事件。

Ⅰ. 自定义View类,继承自需要的View UI类。ex :自定义 MyButton按钮类 extends 基础Button类

Ⅱ. 复写回调函数。ex:public boolean onTouchEvent(MotionEvent event)

每一个事件回调方法都会返回一个boolean值,①.如果返回true:表示该事件已被处理,不再继续向外扩散,②.如果返回false:表示事件继续向外扩散

而说到基于回调就离不开监听机制

几乎所有基于回调的事件处理方法都有一个boolean类型的返回值,该返回值用于表示该处理方法是否能完全处理该事件。
如果处理事件的回调方法返回true,表明该处理方法已经完全处理改事件,该事件不会传播出去。
如果处理事件的回调方法返回false,表明该处理方法并未完全处理该事件,该事件会传播出去。
对于基于回调的时间传播而言,某组件上所发生的事件不仅会激发该组件上的回调方法,也会触发该组件所在Activity的回调方法——只要事件能传播到该Activity。

这里是在模拟器里进行的测试,这里按下键盘(而不是点击),会看到 logcat 中的输出,如下:

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

Handler是一个消息分发对象。

Handler是Android系统提供的一套用来更新UI的机制,也是一套消息处理机制,可以通过Handler发消息,也可以通过Handler处理消息。

在下面介绍Handler机制前,首先得了解以下几个概念:

在子线程执行完耗时操作,当Handler发送消息时,将会调用 MessageQueue.enqueueMessage ,向消息队列中添加消息。 当通过 Looper.loop 开启循环后,会不断地从消息池中读取消息,即调用 MessageQueue.next , 然后调用目标Handler(即发送该消息的Handler)的 dispatchMessage 方法传递消息, 然后返回到Handler所在线程,目标Handler收到消息,调用 handleMessage 方法,接收消息,处理消息。

从上面可以看出,在子线程中创建Handler之前,要调用 Looper.prepare() 方法,Handler创建后,还要调用 Looper.loop() 方法。而前面我们在主线程创建Handler却不要这两个步骤,因为系统帮我们做了。

初始化Looper

从上可以看出,不能重复创建Looper,每个线程只能创建一个。创建Looper,并保存在 ThreadLocal 。其中ThreadLocal是线程本地存储区(Thread Local Storage,简称TLS),每个线程都有自己的私有的本地存储区域,不同线程之间彼此不能访问对方的TLS区域。

开启Looper

发送消息

post方法:

send方法:

在子线程中,进行耗时操作,执行完操作后,发送消息,通知主线程更新UI。

本文讲解了三个方面;Android事件机制;基于监听、基于回调以及Handler消息处理。还有许多没有讲解到的知识点,我总结在了整理的一套Android进阶笔记里面;需要学习进阶的同学可以前往获取: Frame Work源码解析手册 、 Android核心技术进阶手册、实战笔记、面试题纲资料

Ⅶ android事件分发机制 什么意思

android事件分发机制 就是一个触摸事件发生了,从一个窗口传递到一个视图,再传递到另外一个视图,最后被消费的过程,在android中还是比较复杂的传递流程如下:

(1) 事件从Activity.dispatchTouchEvent()开始传递,只要没有被停止或拦截,从最上层的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事件分发与回传机制

[图片上传失败...(image-85aaf7-1630895208631)]

[图片上传失败...(image-8c09b-1630895208631)]

[图片上传失败...(image-25abb8-1630895208631)]

日常处理的部分为RootView下面的ViewGroup和View部分,那么上面的PhoneWindow、DecorView和RootView是做什么用的呢?RootView本身可以作为上下沟通的桥梁使用。

(设计模式-组合模式)

PhoneWindow是Window的实现类,Window是抽象类,DecorView是它的一个内部类。所以,PhoneWindow的大部分消息,都是PhoneWindow通过DecorView传递给下面的View的,同时下面的View传递消息也是通过DecorView回传给PhoneWindow。

事件的传递过程中,主要有三种情况:事件分发(dispatchTouchEvent)、事件拦截(onInterceptTouchEvent)、事件消费(onTouchEvent)。这三种情况均有一个boolean型的返回值来控制事件的传递流程。

为什么只有ViewGroup有事件拦截:因为Activity作为事件分发的开始,拦截了就只能自己处理了;而View作为事件分发的最末端,拦不拦截都需要它处理。中间阶段,拦截可做一些处理。

事件传递的顺序:

Activity -> PhoneWindow -> DecorView -> ViewGroup -> View -> Activity

如果我们点击View1,系统如何传递给View1呢,而不是下面的ViewGroupA或者RootView。很明显,我们需要一种机制来执行消息的分发。而消息分发的最小单位是View,ViewGroup是View的子类,Activity是根布局.

事件消费与否与具体消费无关,仅由返回值决定,true表示消费,false表示不消费。

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

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

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


一 基于监听器的事件处理

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

1)事件源Event Source:产生事件的来源,通常是各种组件,如按钮,窗口等。

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

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


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

举例:

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


[java] view plainprint?

public interface OnLongClickListener {

boolean onLongClick(View v);

}

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


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

[java] view plainprint?

public interface OnTouchListener {

boolean onTouch(View v, MotionEvent event);

}

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

二 基于回调的事件处理

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

举例:

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

[java] view plainprint?

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事件处理机制相关的资料

热点内容
海康威视python通道名 浏览:237
如何用app覆盖全部曲库 浏览:602
变异布林源码 浏览:684
表格加密设置打印区域 浏览:437
卡耐基pdf下载 浏览:922
现在最流行的单片机 浏览:88
机顶盒刷机源码 浏览:985
编码pdf下载 浏览:944
隔壁同学app怎么 浏览:299
c语言宏命令 浏览:542
php卡死源码 浏览:574
time库中的clock函数python 浏览:989
cad视觉移动命令怎么打开 浏览:821
安卓java调用python 浏览:395
java标准时间 浏览:137
华为服务器湖北渠道商云主机 浏览:30
韩式面部护理解压视频 浏览:301
pdf换成jpg图片 浏览:897
dh加密算法 浏览:107
安卓手机如何隐藏微信信息提示 浏览:632