上一篇文章《UIAutomator源码分析之启动和运行》我们描述了uitautomator从命令行运行到加载测试用例运行测试的整个流程,过程中我们也描述了UiAutomatorBridge这个类的重要性

,说它相当于UiAutomation的代理(我们都知道UiAutomator是通过UiAutomation和AccessibilityService进行连接然后获取界面空间信息和注入事件的).那么今天开始我们就围绕这个类以及跟它有关系的类进行进一步的分析。

1. UiAutomatorBridge框架

这一章节我们会先看UiAutomatorBridge的整体框架,往后我会编写其他文章通过一些具体的例子把它们串起来。因为我的mackbook pro上没有安装类图软件,所以下图是手画的 往下我们就去初步描述下UiAutomatorBridge跟每一个相关的类的关系。

2. UiAutomatorBridge与UiAutomation的聚合关系

UiAutomatorBridge拥有一个UiAutomation的成员变量,它们是聚合的关系,注意不是组合,因为UiAutomation不一定只能依赖UiAutomatorBridge而存在,我们上一章节的UiAutomatorTestRunner就拥有一个UiAutomation的成员变量。 一旦UiAutomator工具需要通过UiAutomatorBridge获取界面或者注入事件的时候,就会调用该成员变量.比如下面这个很关键的去获取当前界面的Root Node的方法:

/*     */   public AccessibilityNodeInfo getRootInActiveWindow() {
/* 66 */ return this.mUiAutomation.getRootInActiveWindow();
/* */ }

3. UiAutomatorBridge与QueryController的关联关系

QueryController做的所有事情就是去把UiSelector这个UI控件选择子翻译成真实的适合我们使用的android.view.accessibility.AccessibilityNodeInfo。 UiAutomatorBridge拥有一个成员变量mQueryController保存了QueryController的一个实例:

/*     */   private final QueryController mQueryController;
/* */

当UiObject需要获取一个UiSelector指定的控件信息时,会去调用UiAutomatorBridge的getQueryController方法来获得这个mQueryController对象来进行相应的操作,如以下的UiObject的方法findAccessibilityNodeInfo就是这样做的:

/*      */   protected AccessibilityNodeInfo findAccessibilityNodeInfo(long timeout)
/* */ {
/* 164 */ AccessibilityNodeInfo node = null;
/* 165 */ long startMills = SystemClock.uptimeMillis();
/* 166 */ long currentMills = 0L;
/* 167 */ while (currentMills <= timeout) {
/* 168 */ node = getQueryController().findAccessibilityNodeInfo(getSelector());
/* 169 */ if (node != null) {
/* */ break;
/* */ }
/* */
/* 173 */ UiDevice.getInstance().runWatchers();
/* */
/* 175 */ currentMills = SystemClock.uptimeMillis() - startMills;
/* 176 */ if (timeout > 0L) {
/* 177 */ SystemClock.sleep(1000L);
/* */ }
/* */ }
/* 180 */ return node;
/* */ }

该getQueryController方法会去调用UiAutomatorBridge的getQueryController方法:

/*      */   QueryController getQueryController()
/* */ {
/* 100 */ return UiDevice.getInstance().getAutomatorBridge().getQueryController();
/* */ }

从上面的类图我们可以看到,除了UiAutomatorBridge会调用QueryController做事情外,QueryController又会反过来调用UiAutomatorBridge来做事情,因为如图所描述的,只有UiAutomatorBridge拥有UiAutomation的实例,所以QueryController会持有一个UiAutomatorBridge的实例:

/*     */   private final UiAutomatorBridge mUiAutomatorBridge;

然后在需要的时候再调用UiAutomatorBridge,如下面的获得Root Node的方法:

/*     */   protected AccessibilityNodeInfo getRootNode()
/* */ {
/* 168 */ int maxRetry = 4;
/* 169 */ long waitInterval = 250L;
/* 170 */ AccessibilityNodeInfo rootNode = null;
/* 171 */ for (int x = 0; x < 4; x++) {
/* 172 */ rootNode = this.mUiAutomatorBridge.getRootInActiveWindow();
/* 173 */ if (rootNode != null) {
/* 174 */ return rootNode;
/* */ }
/* 176 */ if (x < 3) {
/* 177 */ Log.e(LOG_TAG, "Got null root node from accessibility - Retrying...");
/* 178 */ SystemClock.sleep(250L);
/* */ }
/* */ }
/* 181 */ return rootNode;
/* */ }

4. UiAutomatorBridge与InteractionController的关联关系

道理与以上的QueryController一样,只是UiAutomatorBridge需要通过InteractionController做的事情不是去获得控件信息,而是去注入事件。

5. UiAutomatorBridge与ShellUiAutomatorBridge的继承关系

UiAutomatorBridge是一个抽象类,里面的方法有以下几个:

  • getRootInActiveWindow :通过UiAutomation获取当前窗口控件xml信息的根节点(通过它可以循环获取所有控件)
  • injectInputEvent :通过UiAutomation注入事件
  • waitForIdle :   通过UiAutomation睡眠指定时间

  • executeCommandAndWaitForAccessibilityEvent:通过UiAutomation执行指定线程的操作然后等待预期的时间返回

  • takeScreenshot :通过UiAutomation进行截图

  • performGlobalAction :  通过UiAutomation去执行一些全局的动作,如打开最近打开过的app列表,回到home界面等

从中可以看到这些动过都是需要通过UiAutomation来执行的,但也有一些动作是不需要用UiAutomation执行的,所以我相信google是为了代码清晰和可维护性,提供了子类ShellUiAutomatorBridge来专门处理那些不需要用到UiAutomation的情况,比如以下的isScreenOn方法就不需要用到UiAutomation,而是直接用PowerManager服务来判断当前屏幕是否是打开的:
/*     */   public boolean isScreenOn()
/* */ {
/* 111 */ IPowerManager pm = IPowerManager.Stub.asInterface(ServiceManager.getService("power"));
/* */
/* 113 */ boolean ret = false;
/* */ try {
/* 115 */ ret = pm.isScreenOn();
/* */ } catch (RemoteException e) {
/* 117 */ Log.e(LOG_TAG, "Error getting screen status", e);
/* 118 */ throw new RuntimeException(e);
/* */ }
/* 120 */ return ret;
/* */ }
作者 自主博客 微信服务号及扫描码 CSDN
天地会珠海分舵 http://techgogogo.com 服务号:TechGoGoGo扫描码: http://blog.csdn.net/zhubaitian

UiAutomator源码分析之UiAutomatorBridge框架的更多相关文章

  1. UiAutomator源码分析之获取控件信息

    根据上一篇文章<UiAutomator源码分析之注入事件>开始时提到的计划,这一篇文章我们要分析的是第二点: 如何获取控件信息 我们在测试脚本中初始化一个UiObject的时候通常是像以下 ...

  2. UiAutomator源码分析之注入事件

    上一篇文章<UiAutomator源码分析之UiAutomatorBridge框架>中我们把UiAutomatorBridge以及它相关的类进行的描述,往下我们会尝试根据两个实例将这些类给 ...

  3. [源码分析] 定时任务调度框架 Quartz 之 故障切换

    [源码分析] 定时任务调度框架 Quartz 之 故障切换 目录 [源码分析] 定时任务调度框架 Quartz 之 故障切换 0x00 摘要 0x01 基础概念 1.1 分布式 1.1.1 功能方面 ...

  4. Duilib源码分析(一)整体框架

    Duilib界面库是一款由杭州月牙儿网络技术有限公司开发的界面开源库,以viksoe项目下的UiLib库的基础上开发(此后也将对UiLib库进行源码分析):通过XML布局界面,将用户界面和处理逻辑彻底 ...

  5. jQuery源码分析之整体框架

    之前只是知道jQuery怎么使用,但是我觉得有必要认真的阅读一下这个库,在分析jQuery源码之前,很有必要对整个jQuery有个整体的框架概念,才能方便后面对jQuery源码的分析和学习,以下是我总 ...

  6. UIAutomator源码分析之启动和运行

    通过上一篇<Android4.3引入的UiAutomation新框架官方简介>我们可以看到UiAutomator其实就是使用了UiAutomation这个新框架,通过调用Accessibi ...

  7. 【转】UIAutomator源码分析之启动和运行

    我们可以看到UiAutomator其实就是使用了UiAutomation这个新框架,通过调用AccessibilitService APIs来获取窗口界面控件信息已经注入用户行为事件,那么今天开始我们 ...

  8. Spark ML源码分析之一 设计框架解读

    本博客为作者原创,如需转载请注明参考           在深入理解Spark ML中的各类算法之前,先理一下整个库的设计框架,是非常有必要的,优秀的框架是对复杂问题的抽象和解剖,对这种抽象的学习本身 ...

  9. Robotium源码分析之Instrumentation进阶-attach

    在分析Robotium的运行原理之前,我们有必要先搞清楚Instrumentation的一些相关知识点,因为Robotium就是基于Instrumentation而开发出来的一套自动化测试框架.鉴于之 ...

随机推荐

  1. 达到HTTP合约Get、Post和文件上传功能——采用WinHttp介面

    于<采用WinHttp实现HTTP协议Get.Post和文件上传功能>一文中,我已经比較具体地解说了怎样使用WinHttp接口实现各种协议. 在近期的代码梳理中,我认为Post和文件上传模 ...

  2. C++生产和使用的临时对象

     所谓暂时对象就是一种无名对象. 它的出现假设不在程序猿的预期之下(比如不论什么pass by value操作都会引发copy操作,于是形成一个暂时对象),往往照成效率上的负担. 但有时候能够制造 ...

  3. RecyclerView0基于使用

    (转载请注明出处:http://www.kennethyo.me/post/android/recyclerviewchu-ji-shi-yong) RecyclerView是Android在v7包中 ...

  4. How to pause the game in Uniy3D

    static float timeScale; Description The scale at which the time is passing. This can be used for slo ...

  5. ACM字符串处理算法经典:字符串搜索

    语法:result=strfind(char str[],char key[]); 参数: str[]:在这个源字符串查找操作 key[]:搜索字符串.不能为空字符串 回报值:     假设查找成功. ...

  6. boost准模板库scoped_ptr指针的使用以及auto_ptr智能指针的对照

    首先我们看看scoped_ptr的基本使用,包括了swap(),get(),reset()的使用,重要的提醒是作用域结束的时候会自己主动析构,无需手动的释放资源: #include<boost/ ...

  7. Laravel nginx 伪静态规则

    最近的各种调查PHP相框(CI, Cake, ThinkPHP, Laravel, Yii)情绪Laravel它看起来很漂亮,下一个深入了解.用发展机Apache,Stage在运行nginx,一旦部署 ...

  8. 菜鸟nginx源码剖析 框架篇(一) 从main函数看nginx启动流程(转)

    俗话说的好,牵牛要牵牛鼻子 驾车顶牛,处理复杂的东西,只要抓住重点,才能理清脉络,不至于深陷其中,不能自拔.对复杂的nginx而言,main函数就是“牛之鼻”,只要能理清main函数,就一定能理解其中 ...

  9. Android Dalvikvm 内存管理理解

    网上非常多文件介绍了 jvm 内存管理的理论,但在 Dalvikvm 中,到底是怎样实现的. 这几天猛看了 Dalvikvm 的源码,说一下我的理解: 在大层面上讲跟理论一样,jvm 把内存分成了一些 ...

  10. Spark1.0.0 学习路径

          2014-05-30 Spark1.0.0 Relaease 经过11次RC后最终公布.尽管还有不少bug,还是非常令人振奋. 作为一个骨灰级的老IT,经过非常成一段时间的消沉,再次被点燃 ...