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

简介:

   Step 30. ViewRoot.dispatchFinishedEvent

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

  1. public final class ViewRoot extends Handler implements ViewParent,  
  2.         View.AttachInfo.Callbacks {  
  3.     ......  
  4.   
  5.     public void dispatchFinishedEvent(int seq, boolean handled) {  
  6.         Message msg = obtainMessage(FINISHED_EVENT);  
  7.         msg.arg1 = seq;  
  8.         msg.arg2 = handled ? 1 : 0;  
  9.         sendMessage(msg);  
  10.     }  
  11.   
  12.     ......  
  13. }  

        和前面的Step 26一样,ViewRoot不是直接处理这个键盘事件,而是把它作为一个消息(FINISHED_EVENT)放在消息队列中去,最后,这个消息由ViewRoot的handleFinishedEvent函数来处理。       Step 31. ViewRoot.handleFinishedEvent

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

  1. public final class ViewRoot extends Handler implements ViewParent,  
  2.         View.AttachInfo.Callbacks {  
  3.     ......  
  4.   
  5.     void handleFinishedEvent(int seq, boolean handled) {  
  6.         final KeyEvent event = (KeyEvent)retrievePendingEvent(seq);  
  7.         ......  
  8.   
  9.         if (event != null) {  
  10.             final boolean sendDone = seq >= 0;  
  11.             if (!handled) {  
  12.                 deliverKeyEventToViewHierarchy(event, sendDone);  
  13.                 return;  
  14.             } else if (sendDone) {  
  15.                 ......  
  16.             } else {  
  17.                 ......  
  18.             }  
  19.         }  
  20.     }  
  21.   
  22.     ......  
  23. }  

        如果InputMethodManager没有处理这个键盘事件,那么ViewRoot就会调用deliverKeyEventToViewHierarchy函数来把这个键盘事件分发给当前激活的Activity窗口来处理。

        Step 32. ViewRoot.deliverKeyEventToViewHierarchy

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

  1. public final class ViewRoot extends Handler implements ViewParent,  
  2.         View.AttachInfo.Callbacks {  
  3.     ......  
  4.   
  5.     private void deliverKeyEventToViewHierarchy(KeyEvent event, boolean sendDone) {  
  6.         try {  
  7.             if (mView != null && mAdded) {  
  8.                 ......  
  9.   
  10.                 boolean keyHandled = mView.dispatchKeyEvent(event);  
  11.             }  
  12.   
  13.             ......  
  14.         } finally {  
  15.             if (sendDone) {  
  16.                 finishInputEvent();  
  17.             }  
  18.         }  
  19.     }  
  20.   
  21.     ......  
  22. }  

        这个函数首先会调用ViewRoot类的成员变量mView的dispatchKeyEvent来处理这个键盘事件,然后最调用ViewRoot类的finishInputEvent来处理手尾工作。

        ViewRoot类的成员变量mView的类型为DecorView,它是由ActivityThread类第一次Resume当前的Activity窗口时创建的,具体可以参考ActivityThread类的handleResumeActivity成员函数,这里就不关注了。

  Step 33. DecorView.dispatchKeyEvent

        这个函数定义在frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java文件中,它是PhoneWindow类的一个内部类:

  1. public class PhoneWindow extends Window implements MenuBuilder.Callback {  
  2.     ......  
  3.   
  4.     private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {  
  5.         ......  
  6.   
  7.         @Override  
  8.         public boolean dispatchKeyEvent(KeyEvent event) {  
  9.             ......  
  10.   
  11.             final Callback cb = getCallback();  
  12.             final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event)  
  13.                 : super.dispatchKeyEvent(event);  
  14.   
  15.             ......  
  16.         }  
  17.   
  18.         ......  
  19.     }  
  20.   
  21.     ......  
  22. }  
        这里通过getCallback函数返回的是当前应用程序的激活的Activity窗口的Window.Callback接口,一般它不为NULL,因此,这个函数会调用Activity类的dispatchKeyEvent来处理这个键盘事件。
        Step 34. Activity.dispatchKeyEvent

 

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

  1. public class Activity extends ContextThemeWrapper  
  2.         implements LayoutInflater.Factory,  
  3.         Window.Callback, KeyEvent.Callback,  
  4.         OnCreateContextMenuListener, ComponentCallbacks {  
  5.     ......  
  6.   
  7.     public boolean dispatchKeyEvent(KeyEvent event) {  
  8.         ......  
  9.   
  10.         View decor = mDecor;  
  11.         if (decor == null) decor = win.getDecorView();  
  12.         return event.dispatch(this, decor != null  
  13.             ? decor.getKeyDispatcherState() : nullthis);  
  14.     }  
  15.   
  16.     ......  
  17. }  
         这里,Activity不是直接处理这个键盘事件,而是通过KeyEvent的dispatch转发一下。注意,KeyEvent的成中函数dispatch的第一个参数的类型是KeyEvent.Callback,而Activity实现了这个接口,因此,这里可以传this引用过去。

 

         Step 35. KeyEvent.dispatch

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

  1. public class KeyEvent extends InputEvent implements Parcelable {  
  2.     ......  
  3.   
  4.     public final boolean dispatch(Callback receiver, DispatcherState state,  
  5.             Object target) {  
  6.         switch (mAction) {  
  7.         case ACTION_DOWN: {  
  8.             ......  
  9.             boolean res = receiver.onKeyDown(mKeyCode, this);  
  10.             ......  
  11.             return res;  
  12.         }  
  13.         case ACTION_UP:  
  14.             ......  
  15.             return receiver.onKeyUp(mKeyCode, this);  
  16.         case ACTION_MULTIPLE:  
  17.             final int count = mRepeatCount;  
  18.             final int code = mKeyCode;  
  19.             if (receiver.onKeyMultiple(code, count, this)) {  
  20.                 return true;  
  21.             }  
  22.             ......  
  23.             return false;  
  24.         }  
  25.         return false;  
  26.     }  
  27.   
  28.     ......  
  29. }  
         这里就根据一个键是按下(ACTION_DOWN)、还是松开(ACTION_UP)或者是一个相同的键被多次按下和松开(ACTION_MULTIPLE)等不同事件类型来分别调用Activity的onKeyDown、onKeyUp和onKeyMultiple函数了。
         Activity窗口处理完这个键盘事件后,层层返回,最后回到Step 32中,调用finishInputEvent事件来处理一些手尾工,下面我们将会看到这些手尾工是什么。




本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966644,如需转载请自行联系原作者
目录
相关文章
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
1216 4
|
8月前
|
存储 Android开发
如何查看Flutter应用在Android设备上已被撤销的权限?
如何查看Flutter应用在Android设备上已被撤销的权限?
341 64
|
存储 安全 Android开发
探索Android与iOS的隐私保护机制
在数字化时代,移动设备已成为我们生活的一部分,而隐私安全是用户最为关注的问题之一。本文将深入探讨Android和iOS两大主流操作系统在隐私保护方面的策略和实现方式,分析它们各自的优势和不足,以及如何更好地保护用户的隐私。
|
7月前
|
消息中间件 Android开发
Android Handler的使用方式以及其机制的简单介绍
Handler 是 Android 中实现线程间通信的重要机制,可传递任意两线程数据。常用场景包括子线程向主线程(UI 线程)传递结果,以及主线程向子线程发送消息。其核心涉及四个类:Handler(发送/接收消息)、Message(消息载体)、MessageQueue(消息队列)和 Looper(消息循环泵)。基本流程为:Handler 发送 Message 至 MessageQueue,Looper 从队列中按 FIFO 取出并处理。
215 0
|
10月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
649 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
10月前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
321 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
算法 Java 数据库
Android 应用的主线程在什么情况下会被阻塞?
【10月更文挑战第20天】为了避免主线程阻塞,我们需要合理地设计和优化应用的代码。将耗时操作移到后台线程执行,使用异步任务、线程池等技术来提高应用的并发处理能力。同时,要注意避免出现死循环、不合理的锁使用等问题。通过这些措施,可以确保主线程能够高效地运行,提供流畅的用户体验。
617 58
|
12月前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
310 14
|
Java Linux 数据库
探索安卓开发:打造你的第一款应用
在数字时代的浪潮中,每个人都有机会成为创意的实现者。本文将带你走进安卓开发的奇妙世界,通过浅显易懂的语言和实际代码示例,引导你从零开始构建自己的第一款安卓应用。无论你是编程新手还是希望拓展技术的开发者,这篇文章都将为你打开一扇门,让你的创意和技术一起飞扬。
219 13
|
搜索推荐 前端开发 测试技术
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。