您好,登录后才能下订单哦!
密码登录
            
            
            
            
        登录注册
            
            
            
        点击 登录注册 即表示同意《亿速云用户服务条款》
        根据上一篇文章《UiAutomator源码分析之注入事件》开始时提到的计划,这一篇文章我们要分析的是第二点:
UiObject appsTab = new UiObject(new UiSelector().text("Apps")); appsTab.click()那么这个过程发生了什么呢?这就是我们接下来要说的事情了。在我没有去分析uiautomator的源代码之前,我一直以为空间查找是在通过UiSelector初始化一个UiObject的时候发生的:
UiObject appsTab = new UiObject(new UiSelector().text("Apps"));appsTab.click()我们进入到代表一个控件的UiObject对应的操作控件的方法去看下就清楚了,以上面的click为例:
/*      */   public boolean click() /*      */     throws UiObjectNotFoundException /*      */   { /*  389 */     Tracer.trace(new Object[0]); /*  390 */     AccessibilityNodeInfo node = findAccessibilityNodeInfo(this.mConfig.getWaitForSelectorTimeout()); /*  391 */     if (node == null) { /*  392 */       throw new UiObjectNotFoundException(getSelector().toString()); /*      */     } /*  394 */     Rect rect = getVisibleBounds(node); /*  395 */     return getInteractionController().clickAndSync(rect.centerX(), rect.centerY(), this.mConfig.getActionAcknowledgmentTimeout()); /*      */   }正式290行的调用触发uiautomator去调用UiAutomation去获取到我们想要的控件节点AccessibilityNodeInfo信息的。    
  
下面我们看下uiautomator是怎么去获取到代表窗口所有控件的根的Root Node的,我们进入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; /*      */   }UiObject对象会首先去获得一个QueryController对象,然后调用该对象的findAccessibilityNodeInfo同名方法:      /*     */   protected AccessibilityNodeInfo findAccessibilityNodeInfo(UiSelector selector, boolean isCounting) /*     */   { /* 143 */     this.mUiAutomatorBridge.waitForIdle(); /* 144 */     initializeNewSearch(); /*     */      /* 146 */     if (DEBUG) { /* 147 */       Log.d(LOG_TAG, "Searching: " + selector); /*     */     } /* 149 */     synchronized (this.mLock) { /* 150 */       AccessibilityNodeInfo rootNode = getRootNode(); /* 151 */       if (rootNode == null) { /* 152 */         Log.e(LOG_TAG, "Cannot proceed when root node is null. Aborted search"); /* 153 */         return null; /*     */       } /*     */        /*     */  /* 157 */       UiSelector uiSelector = new UiSelector(selector); /* 158 */       return translateCompoundSelector(uiSelector, rootNode, isCounting); /*     */     } /*     */   }这里做了两个重要的事情:      /*     */   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; /*     */   }172调用的是UiAutomatorBridge对象的方法,通过我们上面的几篇文章我们知道UiAutomatorBridge提供的方法大部分都是直接调用UiAutomation的方法的,我们进去看看是否如此:/*     */   public AccessibilityNodeInfo getRootInActiveWindow() { /*  66 */     return this.mUiAutomation.getRootInActiveWindow(); /*     */   }果不其然,最终简单明了的直接调用UiAutomation的getRootInActiveWindow来获得根AccessibilityNodeInfo./*      */   public boolean click() /*      */     throws UiObjectNotFoundException /*      */   { /*  389 */     Tracer.trace(new Object[0]); /*  390 */     AccessibilityNodeInfo node = findAccessibilityNodeInfo(this.mConfig.getWaitForSelectorTimeout()); /*  391 */     if (node == null) { /*  392 */       throw new UiObjectNotFoundException(getSelector().toString()); /*      */     } /*  394 */     Rect rect = getVisibleBounds(node); /*  395 */     return getInteractionController().clickAndSync(rect.centerX(), rect.centerY(), this.mConfig.getActionAcknowledgmentTimeout()); /*      */   }从395行可以看到,最终还是把控件节点的信息转换成控件的坐标点进行点击的,至于怎么点击,大家可以参照上一篇文章,无非就是通过建立一个runnable的线程进行点击事件的注入了
  
|    作者  |      自主博客  |      微信  |      CSDN  |   
|    天地会珠海分舵  |      http://techgogogo.com     |      服务号:TechGoGoGo 扫描码:     |      
 免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。 相关阅读
  |