Android UIAutomator如何等待多个条件中的任意一个满足?
如何在Macrobenchmark中等待多个UI元素中的任意一个出现
问题背景
在为应用创建基准配置文件时,需要等待动态Feed完成渲染,但Feed内容是动态的,无法确定具体会渲染哪个目标标签。希望实现等待多个可能标签中的任意一个出现,只要第一个标签出现就返回成功。
现有代码只能等待单个标签:
fun MacrobenchmarkScope.waitForDashboardContent() { device.wait(Until.hasObject(By.res("dashboard_feed")), 10_000) val lazyColumn = device.findObject(By.res("dashboard_feed")) lazyColumn.wait(Until.hasObject(By.res("dashboard_section_title")), 2_000) }
尝试过ChatGPT给出的By.any()方案,但该方法不存在;后续的循环轮询方案虽然可行,但不够优雅且效率较低:
val lazyColumn = device.findObject(By.res("dashboard_feed")) val startTime = System.currentTimeMillis() val timeout = 2000 while (System.currentTimeMillis() - startTime < timeout) { if (lazyColumn.hasObject(By.res("dashboard_section_title")) || lazyColumn.hasObject(By.res("another_section_title"))) { break } Thread.sleep(100) }
更优解决方案
方案1:使用UiAutomator原生的By.or()组合选择器
UiAutomator 2.x提供了By.or()方法,可以将多个BySelector组合成一个逻辑或的选择器,直接用wait()方法等待任意一个目标元素出现。这种方案无需手动轮询,依赖系统UI事件监听,效率更高、代码更简洁。
示例代码:
fun MacrobenchmarkScope.waitForDashboardContent(): Boolean { // 先等待Feed容器加载完成 val feedLoaded = device.wait(Until.hasObject(By.res("dashboard_feed")), 10_000) if (!feedLoaded) return false val lazyColumn = device.findObject(By.res("dashboard_feed")) // 组合多个目标元素的选择器 val anySectionTitleSelector = By.or( By.res("dashboard_section_title"), By.res("another_section_title") ) // 等待任意一个目标元素出现,超时返回false return lazyColumn.wait(Until.hasObject(anySectionTitleSelector), 2_000) }
方案2:自定义Condition(兼容旧版UiAutomator)
如果你的项目依赖的UiAutomator版本不支持By.or(),可以自定义Condition来实现逻辑或判断,同样利用wait()方法的原生监听机制:
fun MacrobenchmarkScope.waitForDashboardContent(): Boolean { val feedLoaded = device.wait(Until.hasObject(By.res("dashboard_feed")), 10_000) if (!feedLoaded) return false val lazyColumn = device.findObject(By.res("dashboard_feed")) // 自定义条件:检查任意一个目标元素是否存在 val anySectionCondition = Condition<Boolean> { input -> input?.run { findObjects(By.res("dashboard_section_title")).isNotEmpty() || findObjects(By.res("another_section_title")).isNotEmpty() } ?: false } return lazyColumn.wait(anySectionCondition, 2_000) }
方案优势对比
- 原生API方案(
By.or()):代码最简洁,性能最优,无需手动控制轮询间隔,系统会自动监听UI变化 - 自定义Condition:兼容性更强,适合旧版本依赖,同样避免了低效的
Thread.sleep()轮询
内容的提问来源于stack exchange,提问作者Felipe Ribeiro R. Magalhaes
相关产品推荐
相关产品推荐

