Android View框架总结(九)KeyEvent事件分发机制

请尊重分享成果,转载请注明出处:

http://blog.csdn.net/hejjunlin/article/details/52335094

本篇开始分析按键消息事件分发(PS:本篇文章中源码均是android 6.0,请知晓)先看下Agenda:

  • ViewRootImpl中的dispatchInputEvent方法
  • View.dispatchKeyEvent方法
  • ViewGroup.dispatchKeyEvent方法
  • Activity.dispatchKeyEvent方法
  • 按键消息事件时序图

ViewRootImpl中的dispatchInputEvent方法

WMS中接受到消息后,会调用ViewRootImpl中的dispatchInputEvent方法,

如下:

ViewRootImpl.java -> dispatchInputEvent()

下面看ViewRootHandler的handleMessage方法:

ViewRootImpl$ViewRootHandler.java -> handleMessage()

以上获取msg中的event,及receiver后,接着调用enqueueInputEvent方法

ViewRootImpl.java -> enqueueInputEvent()

以上方法,由于默认是false,会执行2:

ViewRootImpl.java -> scheduleProcessInputEvents()

以上方法,再给Handler发一条MSG_PROCESS_INPUT_EVENTS(处理的消息)

ViewRootImpl$ViewRootHandler.java -> handleMessage()

ViewRootImpl.java -> doProcessInputEvents()

上面有个循环操作,就是把QueuedInputEvent传递到deliverInputEvent方法中,主要的作用,就是把上面来的按键消息放到队列中去。

ViewRootImpl.java -> deliverInputEvent()

ViewRootImpl提供一个setView方法,是一个public的,会把mView(也就是DecorView),WMS调用这个方法,注意ViewRootImpl并不是一个View,它实际上是一个Handler,它的作用如下:

向DecorView分发收到的用户发起的event事件,如按键,触屏,轨迹球等事件;(这个是在内部类中实现,下面会说)

与WindowManagerService交互,完成整个Activity的GUI的绘制。

看下setView方法

上面有两个内部类,ViewPostImeInputStage,

ViewRootImpl.java$ViewPostImeInputStage

在看processKeyEvent之前,先看onProcess方法:

ViewRootImpl$ViewPostImeInputStage.java -> processKeyEvent

ViewRootImpl.java -> handleDispatchWindowAnimationStopped()

上面有些代码比较长,了解下就行,主要是明白processKeyEvent方法:

KeyEvent是InputEvent的子类,而InputEvent是一个事件的基类。

处理接收的事件及分发事件的过程,那么问题来了?view或者viewGroup是如何收到按键消息派发下来的呢?ViewRootImpl内部类ViewPostImeInputStage中的processKeyEvent()方法中有这么一段

if (mView.dispatchKeyEvent(event)) {//mView是DecorView(书名),但本质上也是View(乳名)

return FINISH_HANDLED;

}

另外键盘消息派发到view或ViewGroup中,在ViewRootImpl另一个内部类ViewPreImeInputStage中的processKeyEvent()方法中也有这么一段如下:

View.dispatchKeyEvent方法

可以看到从这开始就把按键消息派发到了view中去,然后看view中的dispatchKeyEvent():

KeyEvent.java -> dispatch()

ViewGroup.dispatchKeyEvent方法

再来看下ViewGroup中的dispatchKeyEvent()

上面代码总结为:ViewGroup是重写了View的dispatchKeyEvent,如果有子view时,分发按键消息到子view中去。没有,直接由父view分发。

Activity.dispatchKeyEvent方法

到这就完了么?没有,Activity中dispatchKeyEvent,这不是个重写方法:

以上代码总结为:先让actionbar优先处理keyEvent,然后通过window处理,处理不了,到window上的DecorView处理。window和decorview的关系,相当于一个是窗户,一个是粘在窗户上的纸。所以,decorview可理解为窗户上的纸。Activity的dispatchKeyEvent,是用于处理KeyEvent相关,子类可以重写拦截所以的key event消息在分发到window这一层去的时候,所以我们最好做一些正常的处理流程。

主要过程如下:

1、调用onUserInteraction(),可重载该函数在消息派发前做一些处理

2、回调Activity包含的Window对象的superDispatchKeyEvent,该函数继而调用mDecor.superDispatchKveyEent,该函数继而又调用super.dispatchKeyEvent,DecorView的父类是FrameLayout,而FrameLayout未重载dispatchKeyEvent,因此最终调用ViewGroup的dispatchKeyEvent

3、如果DecorView未消耗消息,则调用event的dispatch()函数,这里的第一个参数receiver是Activity对象

写到这,有一个疑问?就是一个消息怎么从window派发到viewRoot中去呢?或者说ViewRoot中的按键消息是从哪来的?

ViewRoot中有一个内部类: W,W是一个Binder子类(static class W extends IWindow.Stub ),用于接收global window manager的各种消息, 如按键消息, 触摸消息等。 ViewRoot有一个W类型的成员mWindow,ViewRoot在构造中创建一个W的instance并赋值给mWindow(mWindow = new W(this);)。 ViewRoot是Handler的子类, W会通过Looper把消息传递给ViewRoot。

按键消息事件时序图

一张图,总结上面的流程:

第一时间获得博客更新提醒,以及更多android干货,源码分析,欢迎关注我的微信公众号,扫一扫下方二维码或者长按识别二维码,即可关注。

如果你觉得好,随手点赞,也是对笔者的肯定,也可以分享此公众号给你更多的人,原创不易

时间: 2024-10-19 09:28:21

Android View框架总结(九)KeyEvent事件分发机制的相关文章

Android:30分钟弄明白Touch事件分发机制

转载: 原文地址  点击打开链接 http://www.cnblogs.com/linjzong/p/4191891.html PS: 对照原文, 添加了一些文字, 表达更清晰(对本人来说) ---------------------------------------------质朴的分割线--------------------------------------------- Touch事件分发中只有两个主角:ViewGroup和View.Activity的Touch事件事实上是调用它内部

Cocos2d-x 3.2 EventDispatcher事件分发机制

本文转载于Cocos2d-x v3.2学习笔记中的(九)事件分发机制(EventDispatcher) EventDispatcher事件分发机制先创建事件,注册到事件管理中心_eventDispatcher,通过发布事件得到响应进行回调,完成事件流. 有五种不同的事件机制: EventListenerTouch 响应触控事件 EventListenerKeyboard 响应键盘事件 EventListenerAcceleration 响应加速器事件 EventListenMouse 响应鼠标事

Android View框架总结(八)ViewGroup事件分发机制

请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52298780 上篇分析了View的事件分发流程,留了一个问题:如果上面的EventButton继承TextView的话,按下抬起,会有一个现象,我可以告诉大家现象:就是只有dispatchTouchEvent ACTION_DOWN,onTouch ACTION_DOWN,onTouchEvent ACTION_DOWN这三个,你移动,或者抬起,是没有MOVE,或者

Android View框架总结(七)View事件分发机制

请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52282833 View布局告一段落,从本篇开始View事件相关分析,今天分析的是View的事件分发机制(PS:本篇文章中源码均是android 6.0,请知晓) View 事件的分发机制 dispatchTouchEvent onInterceptTouchEvent onTouchEvent 案例 事件通常重要的有如下三种: MotionEvent.ACTION_

Android View的事件分发机制探索

概述 Android事件传递机制也是Android系统中比较重要的一块,事件类型有很多种,这里主要讨论TouchEvent的事件在framework层的传递处理机制.因为对于App开发人员来说,理解framework层的事件传递机制,就差不多了. 带着问题来思考整个事件分发过程. 1.为什么要有事件分发过程? 当Android设备的屏幕,接收到触摸的动作时,屏幕驱动把压力信号(包括压力大小,压力位置等)传递给系统底层,然后操作系统经过一系列的处理,然后把触摸事件一层一层的向上传递,最终事件会被准

【朝花夕拾】Android自定义View篇之(六)Android事件分发机制(中)从源码分析事件分发逻辑及经常遇到的一些“诡异”现象

前言 转载请注明,转自[https://www.cnblogs.com/andy-songwei/p/11039252.html]谢谢! 在上一篇文章[[朝花夕拾]Android自定义View篇之(五)Android事件分发机制(上)Touch三个重要方法的处理逻辑][下文简称(五),请先阅读完(五)再阅读本文],我们通过示例和log来分析了Android的事件分发机制.这些,我们只是看到了现象,如果要进一步了解事件分发机制,这是不够的,我们还需要透过现象看本质,去研究研究源码.本文将从源码(基

Android中的事件分发机制(下)——View的事件处理

综述 在上篇文章Android中的事件分发机制(上)--ViewGroup的事件分发中,对ViewGroup的事件分发进行了详细的分析.在文章的最后ViewGroup的dispatchTouchEvent方法调用dispatchTransformedTouchEvent方法成功将事件传递给ViewGroup的子View.并交由子View进行处理.那么现在就来分析一下子View接收到事件以后是如何处理的. View的事件处理 对于这里描述的View,它是ViewGroup的父类,并不包含任何的子元

Android View 事件分发机制 源码解析 (上)

一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~ 首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个MyButton继承Button,然后把跟事件传播有关的方法进行复写,然后添加上日志~ MyButton [java] view plain copy package com.example.zhy_event03; import android.content.Context; import andr

Android View的事件分发机制

准备了一阵子,一直想写一篇事件分发的文章总结一下.这个知识点实在是太重要了. 一个应用的布局是丰富的,有TextView,ImageView,Button等.这些子View的外层还有ViewGroup.如RelativeLayout.LinearLayout.作为一个开发人员,我们会思考.当点击一个button,Android系统是如何确定我点的就是button而不是TextView的?然后还正确的响应了button的点击事件. 内部经过了一系列什么过程呢? 先铺垫一些知识能更加清晰的理解事件分