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

简介:

  Step 14. NativeInputQueue.unregisterInputChannel

        这个函数定义在frameworks/base/core/jni/android_view_InputQueue.cpp文件中:

  1. status_t NativeInputQueue::unregisterInputChannel(JNIEnv* env, jobject inputChannelObj) {  
  2.     sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,  
  3.         inputChannelObj);  
  4.     ......  
  5.   
  6.     { // acquire lock  
  7.         AutoMutex _l(mLock);  
  8.   
  9.         ssize_t connectionIndex = getConnectionIndex(inputChannel);  
  10.         ......  
  11.   
  12.         sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);  
  13.         mConnectionsByReceiveFd.removeItemsAt(connectionIndex);  
  14.   
  15.         connection->status = Connection::STATUS_ZOMBIE;  
  16.   
  17.         connection->looper->removeFd(inputChannel->getReceivePipeFd());  
  18.   
  19.         env->DeleteGlobalRef(connection->inputHandlerObjGlobal);  
  20.         connection->inputHandlerObjGlobal = NULL;  
  21.         ......  
  22.     } // release lock  
  23.   
  24.     ......  
  25.     return OK;  
  26. }  

        真正的注销工作就是这里实现的了,读者可以对照前面介绍应用程序注册键盘消息接收通道过程中的Step 21(NativeInputQueue.registerInputChannel)来分析,它首先是将在之前创建的Connection对象从NativeInputQueue中的mConnectionByReceiveFd向量中删除:

  1. ssize_t connectionIndex = getConnectionIndex(inputChannel);  
  2. ......  
  3.   
  4. sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);  
  5. mConnectionsByReceiveFd.removeItemsAt(connectionIndex);  

        然后再把这个Client端InputChannel的前向管道的读端文件描述符从应用程序主线程中的Looper对象中删除:

  1. connection->looper->removeFd(inputChannel->getReceivePipeFd());  

        这样,这个Activity窗口以后就不会接收到键盘事件了。

 

        最后将Connection对象中的回调对象inputHandlerOjbGlobal对象删除:

  1. env->DeleteGlobalRef(connection->inputHandlerObjGlobal);  
  2. connection->inputHandlerObjGlobal = NULL;  

        回忆一下前面我们在分析InputManager分发键盘消息给应用程序处理时,曾经说到,每当有键盘事件发生时,InputManager首先就会调用NativeInputQueue类的handleReceiveCallback函数。在这个handleReceiveCallback函数里面,NativeInputQueue会找到相应的Connection对象,然后把它里面的内部对象inputHandlerOjbGlobal作为参数来调用Java层的InputQueue类的dispatchKeyEvent函数来通知应用程序,有键盘事件发生了。在InputQueue类的dispatchKeyEvent函数里面,就是通过这个inputHandlerOjbGlobal对象来直正通知到当前激活的Activity窗口来处理这个键盘事件的。

 

        注册在应用程序这一侧的Client端InputChannel被注销以后,回到前面的Step 11中,我们继续分析注销注册在InputManager这一侧的Server端InputChannel。 Step 15. WindowManagerService.Session.remove

        这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java文件中:

  1. public class WindowManagerService extends IWindowManager.Stub  
  2.         implements Watchdog.Monitor {  
  3.     ......  
  4.   
  5.     private final class Session extends IWindowSession.Stub  
  6.             implements IBinder.DeathRecipient {  
  7.         ......  
  8.   
  9.         public void remove(IWindow window) {  
  10.             removeWindow(this, window);  
  11.         }  
  12.   
  13.         ......  
  14.     }  
  15.   
  16.     ......  
  17. }  

 

        这个函数只是简单地调用其外部类WindowManagerService的removeWindow函数来进一步执行操作。

 

        Step 16. WindowManagerService.removeWindow
        这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java文件中:

  1. public class WindowManagerService extends IWindowManager.Stub  
  2.         implements Watchdog.Monitor {  
  3.     ......  
  4.   
  5.     public void removeWindow(Session session, IWindow client) {  
  6.         synchronized(mWindowMap) {  
  7.             WindowState win = windowForClientLocked(session, client, false);  
  8.             if (win == null) {  
  9.                 return;  
  10.             }  
  11.             removeWindowLocked(session, win);  
  12.         }  
  13.     }  
  14.   
  15.     ......  
  16. }  

 

        回忆一下前面我们在分析应用程序注册键盘消息管道的过程时,在Step 11(WindowManagerService.addWindow)中,WindowManagerService为这个即将要激活的Activity窗口创建了一个WindowState对象win,创建的时候,使用了从ViewRoot中传过来的两个参数,分别是一个Session对象session和一个IWindow对象client。 

       在这个函数中,ViewRoot传过来的两个参数session和client和上面说的两个参数是一致的,因此,这个函数首先通过参数session和client得到一个WindowState对象win,然后调用removeWindowLocked来把它从WindowManagerService删除。

        Step 17. WindowManagerService.removeWindowLocked
        这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java文件中:

  1. public class WindowManagerService extends IWindowManager.Stub  
  2.         implements Watchdog.Monitor {  
  3.     ......  
  4.   
  5.     public void removeWindowLocked(Session session, WindowState win) {  
  6.         ......  
  7.   
  8.         win.disposeInputChannel();  
  9.   
  10.         ......  
  11.     }  
  12.   
  13.     ......  
  14. }  

        我们忽略了这个函数的其它逻辑,只关注注销之前注册的Server端InputChannel的逻辑,这里,注销的操作就是调用win的disposeInputChannel进行的了。

       Step 18. WindowState.disposeInputChannel

        这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java文件中:

  1. public class WindowManagerService extends IWindowManager.Stub  
  2.         implements Watchdog.Monitor {  
  3.     ......  
  4.   
  5.     private final class WindowState implements WindowManagerPolicy.WindowState {  
  6.         ......  
  7.   
  8.         void disposeInputChannel() {  
  9.             if (mInputChannel != null) {  
  10.                 mInputManager.unregisterInputChannel(mInputChannel);  
  11.   
  12.                 mInputChannel.dispose();  
  13.                 mInputChannel = null;  
  14.             }  
  15.         }  
  16.   
  17.         ......  
  18.     }  
  19.   
  20.     ......  
  21. }  
        上面说到,在前面分析应用程序注册键盘消息管道的过程时,在Step 11(WindowManagerService.addWindow)中,为当前这个Activity窗口创建了一个WindowState对象,接着创建了一个输入管道后,把Server端的InputChannel保存了在这个WindowState对象的成员变量mInputChannel中,因此,这里,就可以把它取回来,然后调用mInputManager对象的unregisterInputChannel函数来把它注销掉了。




本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966658,如需转载请自行联系原作者
目录
相关文章
|
20天前
|
移动开发 Java Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
【4月更文挑战第3天】在移动开发领域,性能优化一直是开发者关注的焦点。随着Kotlin的兴起,其在Android开发中的地位逐渐上升,但关于其与Java在性能方面的对比,尚无明确共识。本文通过深入分析并结合实际测试数据,探讨了Kotlin与Java在Android平台上的性能表现,揭示了在不同场景下两者的差异及其对应用性能的潜在影响,为开发者在选择编程语言时提供参考依据。
|
22天前
|
数据库 Android开发 开发者
构建高效Android应用:Kotlin协程的实践指南
【4月更文挑战第2天】随着移动应用开发的不断进步,开发者们寻求更流畅、高效的用户体验。在Android平台上,Kotlin语言凭借其简洁性和功能性赢得了开发社区的广泛支持。特别是Kotlin协程,作为一种轻量级的并发处理方案,使得异步编程变得更加简单和直观。本文将深入探讨Kotlin协程的核心概念、使用场景以及如何将其应用于Android开发中,以提高应用性能和响应能力。通过实际案例分析,我们将展示协程如何简化复杂任务,优化资源管理,并为最终用户提供更加流畅的体验。
|
22天前
|
开发框架 安全 Android开发
探索安卓系统的新趋势:智能家居应用的蓬勃发展
随着智能家居概念的兴起,安卓系统在智能家居应用领域的应用日益广泛。本文将探讨安卓系统在智能家居应用开发方面的最新趋势和创新,以及其对用户生活的影响。
14 2
|
25天前
|
缓存 监控 Java
构建高效Android应用:从优化用户体验到提升性能
在竞争激烈的移动应用市场中,为用户提供流畅和高效的体验是至关重要的。本文深入探讨了如何通过多种技术手段来优化Android应用的性能,包括UI响应性、内存管理和多线程处理。同时,我们还将讨论如何利用最新的Android框架和工具来诊断和解决性能瓶颈。通过实例分析和最佳实践,读者将能够理解并实施必要的优化策略,以确保他们的应用在保持响应迅速的同时,还能够有效地利用系统资源。
|
25天前
|
Java Android开发
Android 开发获取通知栏权限时会出现两个应用图标
Android 开发获取通知栏权限时会出现两个应用图标
12 0
|
29天前
|
搜索推荐 Android开发 iOS开发
安卓与iOS系统的用户界面设计对比分析
本文通过对安卓和iOS两大操作系统的用户界面设计进行对比分析,探讨它们在设计理念、交互方式、视觉风格等方面的差异及各自特点,旨在帮助读者更好地理解和评估不同系统的用户体验。
20 1
|
30天前
|
编解码 算法 Java
构建高效的Android应用:内存优化策略详解
随着智能手机在日常生活和工作中的普及,用户对移动应用的性能要求越来越高。特别是对于Android开发者来说,理解并实践内存优化是提升应用程序性能的关键步骤。本文将深入探讨针对Android平台的内存管理机制,并提供一系列实用的内存优化技巧,以帮助开发者减少内存消耗,避免常见的内存泄漏问题,并确保应用的流畅运行。
|
22天前
|
Java Android开发 开发者
构建高效Android应用:Kotlin协程的实践与优化
在响应式编程范式日益盛行的今天,Kotlin协程作为一种轻量级的线程管理解决方案,为Android开发带来了性能和效率的双重提升。本文旨在探讨Kotlin协程的核心概念、实践方法及其在Android应用中的优化策略,帮助开发者构建更加流畅和高效的应用程序。通过深入分析协程的原理与应用场景,结合实际案例,本文将指导读者如何优雅地解决异步任务处理,避免阻塞UI线程,从而优化用户体验。
|
28天前
|
Java 编译器 Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
在开发高性能的Android应用时,选择合适的编程语言至关重要。近年来,Kotlin因其简洁性和功能性受到开发者的青睐,但其性能是否与传统的Java相比有所不足?本文通过对比分析Kotlin与Java在Android平台上的运行效率,揭示二者在编译速度、运行时性能及资源消耗方面的具体差异,并探讨在实际项目中如何做出最佳选择。
17 4
|
1天前
|
存储 缓存 安全
Android系统 应用存储路径与权限
Android系统 应用存储路径与权限
5 0
Android系统 应用存储路径与权限