Step 24. InputQueue.dispatchKeyEvent

这个函数定义在frameworks/base/core/java/android/view/InputQueue.java文件中:

  1. public final class InputQueue {
  2. ......
  3. private static void dispatchKeyEvent(InputHandler inputHandler,
  4. KeyEvent event, long finishedToken) {
  5. Runnable finishedCallback = FinishedCallback.obtain(finishedToken);
  6. inputHandler.handleKey(event, finishedCallback);
  7. }
  8. ......
  9. }

这个函数首先会创建一个FinishedCallback类型的对象finishedCallback,FinishedCallback是InputQueue的一个内部类,它继承于Runnable类。这个finishedCallback对象是提供给当前Activity窗口的,当它处理完毕键盘事件后,需要通过消息分发的方式来回调这个finishedCallback对象,以及InputQueue类处理一个手尾的工作,后面我们会分析到。

这里的inputHandler对象是在前面分析应用程序注册键盘消息接收通道的过程时,在Step 1(ViewRoot.setView)中传进来的:

  1. InputQueue.registerInputChannel(mInputChannel, mInputHandler,
  2. Looper.myQueue());

它是ViewRoot类的一个成员变量mInputHandler。因此,这里将调用ViewRoot类的内部对象mInputHandler的成员函数handleKey来处理键盘事件。

Step 25. InputHandler.handleKey

这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中:

  1. public final class ViewRoot extends Handler implements ViewParent,
  2. View.AttachInfo.Callbacks {
  3. ......
  4. private final InputHandler mInputHandler = new InputHandler() {
  5. public void handleKey(KeyEvent event, Runnable finishedCallback) {
  6. startInputEvent(finishedCallback);
  7. dispatchKey(event, true);
  8. }
  9. ......
  10. };
  11. ......
  12. }

这个函数首先调用其外部类ViewRoot的startInputEvent成员函数来把回调对象finishedCallback保存下来:

  1. public final class ViewRoot extends Handler implements ViewParent,
  2. View.AttachInfo.Callbacks {
  3. ......
  4. private void startInputEvent(Runnable finishedCallback) {
  5. ......
  6. mFinishedCallback = finishedCallback;
  7. }
  8. ......
  9. }

然后再调用其外部类ViewRoot的dispatchKey成员函数来进一步处这个键盘事件。

Step 26. ViewRoot.dispatchKey

这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中:

  1. public final class ViewRoot extends Handler implements ViewParent,
  2. View.AttachInfo.Callbacks {
  3. ......
  4. private void dispatchKey(KeyEvent event, boolean sendDone) {
  5. ......
  6. Message msg = obtainMessage(DISPATCH_KEY);
  7. msg.obj = event;
  8. msg.arg1 = sendDone ? 1 : 0;
  9. ......
  10. sendMessageAtTime(msg, event.getEventTime());
  11. }
  12. ......
  13. }

ViewRoot不是直接处理这个键盘事件,而是把作为一个消息(DISPATCH_KEY)它放到消息队列中去处理,这个消息最后由ViewRoot类的deliverKeyEvent成员函数来处理。
        Step 27. ViewRoot.deliverKeyEvent

这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中:

  1. public final class ViewRoot extends Handler implements ViewParent,
  2. View.AttachInfo.Callbacks {
  3. ......
  4. private void deliverKeyEvent(KeyEvent event, boolean sendDone) {
  5. // If mView is null, we just consume the key event because it doesn't
  6. // make sense to do anything else with it.
  7. boolean handled = mView != null
  8. ? mView.dispatchKeyEventPreIme(event) : true;
  9. ......
  10. // If it is possible for this window to interact with the input
  11. // method window, then we want to first dispatch our key events
  12. // to the input method.
  13. if (mLastWasImTarget) {
  14. InputMethodManager imm = InputMethodManager.peekInstance();
  15. if (imm != null && mView != null) {
  16. ......
  17. imm.dispatchKeyEvent(mView.getContext(), seq, event,
  18. mInputMethodCallback);
  19. return;
  20. }
  21. }
  22. ......
  23. }
  24. ......
  25. }

ViewRoot在把这个键盘事件分发给当前激活的Activity窗口处理之前,首先会调用InputMethodManager的dispatchKeyEvent成员函数来处理这个键盘事件。InputMethodManager处理完这个键盘事件后,再回调用这里的mInputMethodCallback对象的finishedEvent成员函数来把键盘事件分发给当前激活的Activity窗口处理。当然,在把这个键盘事件分发给InputMethodManager处理之前,ViewRoot也会先把这个键盘事件分发给当前激活的Activity窗口的dispatchKeyEventPreIme成员函数处理。

Step 28. InputMethodManager.dispatchKeyEvent

这个函数定义在frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java文件中。这是一个输入法相关的类,我们这里就不关注了,只要知道当输入法处理完成之后,它就会调用ViewRoot类的mInputMehtodCallback对象的finishedEvent成员函数。

Step 29.  InputMethodCallack.finishedEvent

这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中:

  1. public final class ViewRoot extends Handler implements ViewParent,
  2. View.AttachInfo.Callbacks {
  3. ......
  4. static class InputMethodCallback extends IInputMethodCallback.Stub {
  5. private WeakReference<ViewRoot> mViewRoot;
  6. public InputMethodCallback(ViewRoot viewRoot) {
  7. mViewRoot = new WeakReference<ViewRoot>(viewRoot);
  8. }
  9. public void finishedEvent(int seq, boolean handled) {
  10. final ViewRoot viewRoot = mViewRoot.get();
  11. if (viewRoot != null) {
  12. viewRoot.dispatchFinishedEvent(seq, handled);
  13. }
  14. }
  15. ......
  16. }
  17. ......
  18. }

这个函数最终调用ViewRoot的dispatchFinishedEvent来进一步处理。

本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966639,如需转载请自行联系原作者

Android应用程序键盘(Keyboard)消息处理机制分析(20)相关推荐

  1. Android系统中的Binder通信机制分析(7)- Java 层的 Binder 机制

    声明 其实对于Android系统Binder通信的机制早就有分析的想法,记得2019年6.7月份Mr.Deng离职期间约定一起对其进行研究的,但因为我个人问题没能实施这个计划,留下些许遗憾- 文中参考 ...

  2. Android应用程序键盘(Keyboard)消息处理机制分析(3)

    Step 15. Looper.pollOnce 这个函数定义在frameworks/base/libs/utils/Looper.cpp文件中,具体可以参考前面Android应用程序消息处理机制(L ...

  3. Android应用程序键盘(Keyboard)消息处理机制分析(12)

    Step 12. InputChannel.openInputChannelPair 这个函数定义在frameworks/base/core/java/android/view/InputChanne ...

  4. Android应用程序线程消息循环模型分析(5)

      从AsyncTask的实现可以看出,当我们第一次创建一个AsyncTask对象时,首先会执行下面静态初始化代码创建一个线程池sExecutor: private static final Bloc ...

  5. Android应用程序线程消息循环模型分析

    出自:http://blog.csdn.net/luoshengyang/article/details/6905587 我们知道,Android应用程序是通过消息来驱动的,即在应用程序的主线程(UI ...

  6. 以下未发布-Android的多线程以及异步消息处理机制,android移动开发基础案例教程源码

    1.Message: Message 是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间进行数据交换.除了 what 字段,还可以使用 arg1 和 arg2 来携带整型数据,使用 ...

  7. Android应用程序键盘(Keyboard)消息处理机制分析(26)

    Step 7. LocalWindowManager.removeViewImmediate 这个函数定义在frameworks/base/core/java/android/view/Window. ...

  8. Android应用程序键盘(Keyboard)消息处理机制分析(17)

    Step 11. InputDispatcher.dispatchOnceInnerLocked 这个函数定义在frameworks/base/libs/ui/InputDispatcher.cpp文 ...

  9. Android应用程序键盘(Keyboard)消息处理机制分析(14)

    3. InputManager分发键盘消息给应用程序的过程分析 在分析InputManager分发键盘消息给应用程序的过程之前,我们先假设现在没有键盘事件发生,因此,InputManager中的Inp ...

最新文章

  1. ECEF rectangular coordinate system(ECEF直角坐标系)
  2. 开关机自动执行脚本方法[以及切换用户执行命令方法]
  3. 成功解决matplotlib绘图的时候横坐标或纵坐标文本显示不全/显示一半/显示不完整的问题
  4. 20171115_Python学习五周三次课
  5. 【视频】vue生命周期函数
  6. 【转】BLE 学习记录
  7. android传递数据bundle封装传递map对象
  8. 刚刚,SeetaFace版本升级!新增活体检测等功能
  9. 38 NoSQL-memcached
  10. 大学学计算机用游戏本好吗,大学学建筑学用什么配置的笔记本电脑好?
  11. 操作对象_word选择操作技巧:不同操作对象,选择方式不同?
  12. DMX512协议解析
  13. QNX分布式实时操作系统初步认识-QNX系统了解认识
  14. unlock-music-desktop解锁加密音乐桌面版
  15. uni-app实现问卷调查试卷
  16. 【web-攻击验证机制】(3.2.3)验证机制设计缺陷:“记住密码” 功能、用户伪装功能、证书确认不完善
  17. 360校招笔试题总结2
  18. mysql 前几个月的时间_MYsql 查询 查询当前周、月份及前几个月的数据(时间 查询)...
  19. 华米科技:庇佑之下,黄汪难设温柔乡
  20. 群晖NAS 7.X 搭建个人博客网站并发布公网 1/8

热门文章

  1. 改变程序员的一本书 | 每日趣闻
  2. Foxmail邮件如何导入Outlook中
  3. 唯一聚集索引上的唯一和非唯一非聚集索引
  4. MySQL创建相同表和数据命令
  5. Spring 基于Java配置
  6. Spring @Lazy
  7. 阿里员工在用的黑科技 今年云栖要公开了!
  8. WPF Effect 造成的字体模糊
  9. mysql用户管理,常用sql语句,mysql数据库备份恢复
  10. ThinkPHP关联模型详解