Android之UiAutomator测试框架源码分析(第十七篇:UiObject2的legacySetText方法分析)

(注意:本文基于UI Automator测试框架版本为2.2.0)   

    无意间在UiObject2中看见legacySetText()方法,发现它被hide修饰,特别好奇这个方法做了什么,就拿来分析一番!如果你通过前面多篇文章的学习,一定知道一个UiObject2对象表示一个控件,该控件可以是普通的控件(View),也可以是一个控件组(ViewGroup)!接下来学习legacySetText()方法的实现,看看我们能发现什么?

 

legacySetText方法

/**
     * Set the text content by sending individual key codes.
     * @hide
     */
    public void legacySetText(String text) {
        AccessibilityNodeInfo node = getAccessibilityNodeInfo();

        // Per framework convention, setText(null) means clearing it
        if (text == null) {
            text = "";
        }

        CharSequence currentText = node.getText();
        if (!text.equals(currentText)) {
            InteractionController ic = getDevice().getInteractionController();

            // Long click left + center
            Rect rect = getVisibleBounds();
            ic.longTapNoSync(rect.left + 20, rect.centerY());

            // Select existing text
            getDevice().wait(Until.findObject(By.descContains("Select all")), 50).click();
            // Wait for the selection
            SystemClock.sleep(250);
            // Delete it
            ic.sendKey(KeyEvent.KEYCODE_DEL, 0);

            // Send new text
            ic.sendText(text);
        }
    }

该方法为hide修饰,定义在UiObject2类中,我们如果不使用反射技能,自然是不能直接调用该方法的!那么它值得我们使用吗?我在UI Automator测试框架中并没有找到它被使用的痕迹,可能是Google内部还在自己进行测试,也许下一个版本就会成为UiObject2的public修饰的API了,我们继续代码分析吧……

1、最先调用getAccessibilityNodeInfo()方法,这个方法返回的AccessibilityNodeInfo对象表示的是已匹配的控件,临时创建一个局部变量node专门负责保存该对象的引用,后面看看要用这个node做什么!

2、接着作者按照框架公约,对传入的text为null时的情况做处理,如果传入的text为null就表示是要清空控件的文本信息,所以此处为text又赋值了一个空的字符串对象

3、代码继续,先通过AccessibilityNodeInfo对象的getText方法()获得控件上的文本信息,比如EditText控件上的文本信息,此文本信息由创建的局部变量currentText负责保存,getText的返回值是一个CharSequence对象,CharSequence本身是个接口,String对象实现了CharSequence接口

4、接下来判断传入的文本信息text是否与当前控件已经显示的文本信息currentText相同,只有不相同的情况下,才会继续执行一系列的操作,我们马上看一下这部分代码,先调用getDevice()方法,获取一个UiDevice对象并调用它的getInteractionController()方法,该方法会返回一个InteractionController对象,那么UiDevice对象持有的InteractionController对象提供了哪些功能呢?(答案见本文末端的官方注释)一般我们只要进去看看它提供了哪些方法、还有该类中的注释可以了!UiDevice对象的很多功能底层完全是靠InteractionController做的具体实现!(InteractionController需要单开文章学习),该对象临时赋值给一个称作ic的局部变量保存!

5、代码继续,这次先获取表示控件矩形在屏幕中的位置,这个矩形的信息是封装在一个Rect对象中的,接着做一个长按操作,x坐标就采用Rect对象持有的left值+20,这是为了可以点击的位置向里侧靠近一些(屏幕左上角的坐标是[0,0]),而y坐标就直接使用Rect对象中封装的bottom值!

6、接下来的语句,则是在当前Window中查找一个desc属性的文本信息是“Selector All”的控件,因为使用了UiDevice对象的wait方法,所以这里插桩线程会有等待情况,限制了最大等待50s的时间去查找一个desc属性的文本信息是“Selector All”的控件,接着会调用click方法去做点击操作,点击操作是为了选中控件!(注意:这里代码写的不好,一旦找不到匹配的控件,UiDevice的wait方法将会返回一个null,此时再调用UiObject2的click()方法,一定会抛出一个NullPointerException对象的!,果然是hide方法,不知道下一个版本,大佬们会再用这个方法怎么做?还是直接把这个方法干掉!)

7、再接下来的语句更过分,直接让当前线程休眠250s,然后调用InteractionController对象的sendKey方法,执行一个实体的清除按钮事件KEYCODE_DEL,然后通过InteractionController对象的sendText方法,为控件设置上传入的文本信息!!

我靠,如果传入的文本信息text与目前控件的一致,上面所属的第4个步骤的部分代码、以及5、6、7步骤的代码就不会再执行了…………

 

总结

1、InteractionController负责向系统中注入用户事件,比如触摸事件(包括滑动)和文本按键事件。为此,它只需要知道触摸事件的坐标和文本输入事件的文本。InteractionController不执行同步。它将触发触摸和文本输入事件的速度与它接收事件的速度一样快。所有空闲同步都在查询View的层次结构之前执行。请看{@link QueryController}

2、这个方法是hide修饰的,应该是没有经过测试,感觉下一个Ui Automator版本应该会放出来,另外该方法内部的实现语句getDevice().wait(Until.findObject(By.descContains("Select all")), 50).click();   就是这一句,没想到我已经率先采用了……哈哈!

3、还有InteractionController对象,实现了这么多功能,这也是UiDevice对象持有它的原因……

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值