Android 用户事件输入路径(Message/Event, Dispatch Path)

Android用户事件输入路径

 

1 输入路径的一般原理

      按键,鼠标消息从收集到最终将发送到焦点窗口,要经历怎样的路径,是Android GWES设计方案中需要详细考虑的问题。按键,鼠标等用户消息消息的处理可分为不同的情况进行判定:

(1)用户输入根据系统状况是否应该派送。如在ScreenOff的情况下,在按键属于特殊按键的情况下等

(2)是否有拦截Listener

(3)对按键事件来讲,是否存在输入法

(4)是否是焦点终点

(5)是否为焦点切换按相关键

这些情况都是设计输入路径需要考虑的基本条件。

1.1一般的输入路径设计

该输入路径实际上是指的按键消息(MSG_KEYDOWN,MSG_KEYUP, MSG_LongPress)的输入路径,即从活动主窗口到焦点窗口所经历的路程。

inputNormal

将信息输入路径分为两步:

Step 1)窗口管理器将信息发送到活动窗口

Step 2)活动窗口通过缺省处理函数将该消息一层层的传递到焦点。

这样应用程序可以在活动View的处理函数中来预先处理用户输入信息,从而增强应用对用户信息的控制力。

inputxxx1

传递路径是通过View的缺省处理函数Onxxx来完成。通过ActiveView ->focus->focus->focus的链条关系,一级一级的将按键消息MSG_KEYDOWN,MSG_KEYUP, MSG_CHAR等传递到focus窗口。

inputxxx2

此时用户按键输入先发送到输入法窗口,经过输入法管理器处理,过滤后将输入法产生的结果放置到焦点View。

1.3输入系统整体流程

下面示意图是Android输入系统的数据流途径,通过WM的输入系统线程收集消息,分发到Focus Activity消息队列,然后通过消息系统派发。

InputSystemPATH

 

 

2 Android输入路径详细描述

 

  2.1 第一步:用户数据收集及其初步判定

     KeyInputQ在WindowMangerService中建立一个独立的线程InputDeviceReader,使用Native函数readEvent来读取Linux Driver的数据构建RawEvent,放入到KeyQ消息队列中。

inputDeviceReader

preProcessEvent()@KeyInptQ@KeyInputQueue.java这个是在输入系统中的第一个拦截函数原型。KeyQ重载了preProcessEvent()@WindowManagerService.java。在该成员函数中进行如下动作:

(1) 根据PowerManager获取的Screen on,Screen off状态来判定用户输入的是否WakeUPScreen。

(2) 如果按键是应用程序切换按键,则切换应用程序。

(3) 根据WindowManagerPolicy觉得该用户输入是否投递。

2.2 第二步 消息分发第一层面

InputDispatcherThread从KeyQ中读取Events,找到Window Manager中的Focus Window,通过Focus Window记录的mClient接口,将Events专递到Client端。

inputDispatcherThread

如何将KeyEvent对象传到Client端:

在前面的章节(窗口管理ViewRoot,Window Manager Proxy)我们已经知道:在客户端建立Window Manager Proxy后,添加窗口到Window Manager service时,带了一个跟客户ViewRoot相关的IWindow接口实例过去,记录在WindowState中的mClient成员变量中。通过IWindow这个AIDL接口实例,Service可以访问客户端的信息,IWindow是Service连接View桥梁。

IWindow

看看在Client ViewRootKeyEvent的分发过程

IWindow:dispatchKey(event)

dispatchKey(event)@W@ViewRoot@ViewRoot.java

       ViewRoot.dispatchKey(event)@ViewRoot.java

                     message>

                     sendMessageAtTime(msg)@Handler@Handler.java

至此我们通过前面的Looper,Handler详解章节的分析结论,我们可以知道Key Message已经放入到应用程序的消息队列。

2.3第三步:应用消息队列分发

   消息的分发,在Looper,Handler详解章节我们分析了Looper.loop()在最后后面调用了handleMesage.

          …

           ActivityThread.main()

                Looper.loop()

                  ViewRoot$RootHandler().dispatch()

                      handleMessage

                          ....

      注意到在分发的调用msg.target.dispatch(),而这个target在第二层将消息sendMessageAtTime到消息队列时填入了mag.target=this即为msg.target=ViewRoot实例。所有此时handleMessage就是ViewRoot重载的handleMessage函数。

handlerMessage@ViewRoot@ViewRoot.java

       deliverkeyEvent

            如果输入法存在,dispatchKey到输入法服务。

            否则deliverKeyEventToViewHierarchy@ViewRoot.java

     在这里需要强调的是,输入法的KeyEvent的拦截并没有放入到Window Manager Service中,而是放入到了客户端的RootView中来处理。

2.4第四步:向焦点进发,完成焦点路径的遍历。

focuspath1

分发函数调用栈

deliverKeyEventToViewHierarchy@ViewRoot.java

mView.dispatchKeyEvent:mView是与ViewRoot相对应的Top-Level View.如果mView是一个ViewGroup则分发消息到他的mFocus。

mView.dispatchKeyEvent @ViewGroup  (ViewRoot@root)

               Event.dispatch

                        mFocus.dispatchKeyEevnet

    如果此时的mFocu还是一个ViewGroup,这回将事件专递到下一层的焦点,直到mFocus为一个View。通过这轮调用,就遍历了焦点Path,至此,用户事件传递完成一个段落。

2.5第五步 缺省处理

如果事件在上述Focus View没有处理掉,并且为方向键之类的焦点转换相关按键,则转移焦点到下一个View。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java中的"java.awt.eventdispatchthread"是一个线程,它负责处理用户界面组件上的事件,如按钮点击、文本框更新等。这个线程是单独的,主要是为了避免在处理事件时阻塞主线程,从而让用户界面变得更加流畅。 ### 回答2: Java.awt.eventdispatchthread是一个Java AWT(Abstract Window Toolkit)中的线程类,用于处理和分发事件。它是AWT事件模型的核心部分,负责接收和分发用户输入事件。 Java.awt.eventdispatchthread负责管理用户交互产生的各种事件,包括鼠标点击、键盘敲击、窗口操作等。当用户触发这些事件时,事件首先被底层操作系统捕获,然后传递给Java.awt.eventdispatchthread进行处理。 Java.awt.eventdispatchthread是单线程的,它采用事件队列(Event Queue)的方式处理事件。当一个事件发生时,它会将该事件加入到事件队列中。然后按照事件的先后顺序,逐个处理队列中的事件。这种方式保证了事件的顺序一致性,避免了多个事件同时处理的问题。 除了事件的分发以外,Java.awt.eventdispatchthread还负责调用事件监听器(Event Listener)。事件监听器是在应用程序中定义的,用于响应特定事件的回调函数。当事件被分发到监听器时,Java.awt.eventdispatchthread会调用监听器中定义的方法进行逻辑处理。 Java.awt.eventdispatchthread的工作原理如下: 1. 事件被捕获并传递给Java.awt.eventdispatchthread。 2. Java.awt.eventdispatchthread将事件加入到事件队列中。 3. 依次处理事件队列中的事件。 4. 根据事件类型找到相应的事件监听器。 5. 调用监听器中定义的方法进行事件处理。 总之,Java.awt.eventdispatchthread是Java AWT中的关键线程类,负责接收、管理和分发用户输入的各种事件。它使用事件队列的方式保证事件的有序处理,并调用相应的事件监听器进行逻辑处理。 ### 回答3: Java AWT EventDispatchThread(事件调度线程)是Java AWT(图形用户界面)库中的一个线程,它的主要作用是接收、处理和分发所有的AWT事件。它是一个单线程,用于处理UI事件和操作。 Java AWT EventDispatchThread是一种特殊的线程,它负责处理用户界面事件的顺序和同步。当用户与界面进行交互,比如点击按钮、输入文本等操作时,这些操作都会被封装为AWT事件,并由EventDispatchThread按照先后顺序进行处理。 EventDispatchThread的作用主要有以下几个方面: 1. 事件的分发:当用户触发了某个事件EventDispatchThread负责将该事件分发给对应的组件进行处理。这样可以保证事件被按照正确的顺序执行,防止事件处理出现混乱的情况。 2. 事件的处理:EventDispatchThread负责将事件发送到目标组件,并调用相应的事件处理方法。例如,当用户点击按钮时,EventDispatchThread会调用按钮的actionPerformed方法来处理点击事件。 3. 界面的刷新:EventDispatchThread负责处理界面的刷新操作。当某个组件的状态发生变化时,EventDispatchThread会负责重新绘制该组件,以保持界面的一致性。 综上所述,Java AWT EventDispatchThread是一个专门负责处理UI事件和操作的线程。它负责接收、处理和分发所有的AWT事件,保证事件的顺序和同步性,确保界面的正确响应和刷新。因此,了解和理解EventDispatchThread的工作原理对于开发Java AWT应用程序是非常重要的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值