You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 15:27:18