Android之UiAutomator测试框架源码分析(第六篇:UiDevice的注册与反注册UiWatcher功能分析)

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

前言

    UiDevice中与UiWatcher相关的API共计6个,注册与反注册UiWatcher功能非常重要,只有注册成功的UiWatcher,才能起到监听控件的作用。UiWatcher是一个interface,每一个实现UiWatcher的类,都表示一种具备监听控件的能力,正因如此,每当我们在插桩测试过程中,发现代表控件的UiObject、UiObject2对象出现找不到的情况时,就会自动通知每个注册的UiWatcher,UiWatcher收到通知后,会回调实现的checkCondition()方法,我们可以在UiWatcher实现类中的checkConditioni()中编写一些找不到控件的处理逻辑。UiWatcher自定义的处理逻辑只要完善,即可以确保测试项目的绝对稳定性(妥妥的),比如我们可以在UiWatcher中处理弹窗(罪魁祸首),处理网络状态以及你能想到可以做的任何影响控件被找到的逻辑,本篇文章我们学习一下UiWatcher是如何注册到UiDevice中的,又是如何从UiDevice中取消注册的,这两个功能是在UiDevice中的registerWatcher()方法、removeWatcher()方法实现的!你平时可以注册局部的UiWatcher、也可以注册全局的UiWatcher,局部的UiWatcher只对特定的控件生效,全局的UiWatcher对所有控件生效!

registerWatcher()方法用于注册UiWatcher

removeWatcher()方法用于反注册UiWatcher

 

registerWatcher()方法分析

用于注册UiWatcher的方法,该方法位于UiDevice类中,接受两个参数,第一个参数是一个String对象,表示注册UiWatcher对象的名字,第二个参数为注册的UiWatcher对象,每个UiWatcher对象表示一个Ui观察者(控件监听者)

    public void registerWatcher(String name, UiWatcher watcher) {
        Tracer.trace(name, watcher);
        if (mInWatcherContext) {
            throw new IllegalStateException("Cannot register new watcher from within another");
        }
        mWatchers.put(name, watcher);
    }

1、追踪线程堆栈信息,用于Debug

将传入的参数name与watcher传入Tracer的静态方法trace()中,这个方法会记录线程的堆栈信息

2、防止在UiWatcher中再次注册UiWatcher

判断标志位mInWatcherContext,它是UiDevice对象持有的一个boolean型标志位,true表示正在处于UiWatcher的处理逻辑中,false则表示不在UiWatcher处理逻辑中,使用mInWatcherContext标志位可以防止我们在UiWatcher的checkForCondition()方法中再去注册一个新的UiWatcher对象,即不允许从另一个观察者中注册新的观察者,如果我们违反规则就会得到一个IllegalStateException异常对象。其实这个mInWatcherContext标志位还有另外一个作用,它还可以防止UiWatcher的checkForCondition()方法被连续多余的触发,在触发UiWatcher的方法runWatchers()中也同时使用了该标志位,这个我们后面再了解。(mInWatcherContext的两个作用)

3、注册UiWatcher到一个容器中

通过上面的检查,到了真正注册UiWatcher对象的位置,通过mWatchers的put()方法将name与watcher一起注册。那么mWathcers是什么呢?mWatchers是UiDevice对象持有的一个HashMap对象,此时的name作为key,watcher则是作为value,只要把UiWatcher保存到容器中,即表示成功注册一个UiWatcher!

 

removeWatcher()方法分析

用于反注册UiWatcher的方法,该方法位于UiDevice类中,传入参数表示UiWatcher的名字

    public void removeWatcher(String name) {
        Tracer.trace(name);
        if (mInWatcherContext) {
            throw new IllegalStateException("Cannot remove a watcher from within another");
        }
        mWatchers.remove(name);
    }

注册的UiWatcher对象都被保存到UiDevice对象持有的一个HashMap对象mWatchers中了,反注册UiWatcher,只需要从HashMap对象中删除对应的元素即可,我们看下具体的实现过程

1、追踪线程堆栈信息,用于Debug

首先也是线程堆栈的跟踪,为了方便调试

2、防止在UiWatcher中反注册一个UiWatcher

标志位mInWatcherContext,不允许在UiWatcher中移除一个UiWatcher,否则会得到一个IllegalStateException对象

3、反注册UiWatcher

从UiDevice对象持有的HashMap对象mWatchers中执行删除元素,为HashMap的remove()方法传入表示UiWatcher名字的key对象name即可!

 

总结

1、注册UiWatcher功能:将UiWatcher对象的引用保存在UiDevice对象持有的HashMap对象mWatchers中,完成UiWatcher的注册

2、反注册UiWatcher功能:从UiDevice对象持有的HashMap对象mWatchers中删除元素,完成UiWatcher的反注册

3、每个UiWatcher对象保存在HashMap对象中,注册UiWatcher使用的key对象统一保管,这样才方便随时根据需求情况注册与取消注册UiWatcher对象

4、UiWatcher的checkForCondition()方法中不能再进行UiDevice对象的注册与反注册,否则会得到一个IllegalStateException对象!

以下截图是标志位mInWatcherContext唯一赋值为true的位置,说明此时处于UiWatcher执行过程中,runWatchers()方法也位于UiDevice中,它的功能是回调所有已注册的UiWatcher的checkForCondition()方法!

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值