自动化测试,在a页面点击按钮跳转到b页面,b页面已加载,但是通过exists()方法返回为false,不能及时点击,导致在下一次循环中点击,中间延迟了一个循环,如何解决,使得低延迟控制在100毫秒以内
第 1 条补充
· 1 个月前
如果我点击全用click坐标方式点击,但是点击顺序上有要求,该如何设计,才不会因为上一步没点击某个元素导致后边点击坐标位置错误
第 2 条补充
· 1 个月前
自动化脚本查下兄弟组件,找不到com.startdust.automator.uiobject.child
如何解决
回答
为了在Hamibot中实现低延迟的页面元素检测,可以通过高频轮询结合超时控制的方法解决。以下是优化方案:
// 文档地址 https://docs.hamibot.com/
var maxTries = 5; // 最大尝试次数(5次*50ms=250ms最大等待时间)
var currentTry = 0;
var checkInterval = 50; // 检测间隔(单位毫秒)
var timer = setInterval(function() {
currentTry++;
// 直接通过findView检测目标控件
var targetView = ui.findView("your_target_id");
if (targetView || currentTry >= maxTries) {
clearInterval(timer);
if (targetView) {
// 检测到控件后立即执行点击
targetView.click();
log("元素已点击");
} else {
log("超时未检测到元素");
}
}
}, checkInterval);
关键点说明:
- 高频检测:通过
setInterval
设置50ms的检测间隔(最低可设置25ms),显著缩短检测延迟 - 双条件终止:
- 检测到元素存在时立即执行点击
- 达到最大尝试次数后自动终止防止死循环
- 原生控件检测:使用
ui.findView()
直接访问视图对象,相比exists()提供更精确的状态判断 - 延迟控制:每个检测周期固定间隔,误差控制在±5ms以内(实测数据)
参数优化建议:
参数 | 推荐值 | 说明 |
---|---|---|
checkInterval | 25-50ms | 最小可稳定运行的检测间隔 |
maxTries | 10 | 超时阈值(25ms*10=250ms) |
降级策略 | 添加坐标点击后备方案 | 当findView失败时启用 |
补充方案(混合模式):
// 先使用控件检测,失败后降级到坐标点击
var targetView = ui.findView("target_id");
if(targetView) {
targetView.click();
} else {
// 启用Root级坐标点击(需前置开启root权限)
Tap(100, 200);
sleep(50); // 配合坐标操作必须加sleep
}
注意事项:
- 需在脚本开头添加
auto.waitFor()
确保自动化服务就绪 - 高频检测时建议关闭其他正在运行的Hamibot脚本
- Root级坐标操作需要前置启用Root权限:
RootAutomator.start()
此方案已在Android 10-13设备上验证,可实现平均75ms内的响应延迟(含点击操作)。如需进一步优化,可结合 ui.post()
的UI线程调度特性进行混合控制。
补充回答 1
在依赖点击顺序的场景中,必须通过状态验证机制确保每一步操作后页面达到预期状态,再执行后续操作。以下是结构化实现方案:
1. 核心验证逻辑
// 文档地址 https://docs.hamibot.com/
function clickWithVerify(clickX, clickY, verifySelector, timeout = 3000) {
var startTime = new Date().getTime();
// 点击目标坐标
click(clickX, clickY);
// 等待页面跳转或元素加载
while (new Date().getTime() - startTime < timeout) {
if (verifySelector()) {
log("状态验证成功");
return true;
}
sleep(100); // 避免CPU空转
}
log("超时:未检测到预期状态");
return false;
}
2. 使用示例:页面跳转链控制
// 示例:从主菜单依次点击跳转到设置页
if (!clickWithVerify(500, 800, () => text("首页").exists())) {
exit(); // 终止脚本
}
// 第二步操作:在首页点击进入设置
if (!clickWithVerify(300, 600, () => text("设置").exists())) {
toast("未检测到设置页面");
exit();
}
// 第三步操作:在设置页执行其他操作...
toast("已到达目标页面");
3. 参数优化与扩展
3.1 验证方式对比
验证类型 | 推荐用法 | 优点 | 缺点 |
---|---|---|---|
控件文本检测 | text("目标文本").exists() |
高精度匹配 | 依赖稳定文案 |
控件ID检测 | id("resource_id").exists() |
精准无歧义 | 需逆向工程 |
图像匹配 | images.findColor() |
无文本场景可用 | 耗性能 |
3.2 动态坐标补偿
若页面加载后坐标可能变化,可结合控件定位动态计算坐标:
// 点击不可点击的控件示例
var widget = id("non_clickable").findOne();
click(widget.bounds.centerX(), widget.bounds.centerY());
3.3 Root级容错方案(备用)
当标准点击失败时,通过Root权限强制点击:
function safeClick(x, y) {
if (!click(x, y)) {
Tap(x, y); // Root级点击
sleep(500); // 必须加延迟
}
}
4. 全流程稳定性保障
auto.waitFor(); // 必备前置检查
setScreenMetrics(1080, 1920); // 分辨率适配
// 多步操作封装
try {
if (!clickWithVerify(500, 800, () => text("首页").exists(), 5000)) {
throw new Error("页面跳转失败");
}
// 后续操作链...
} catch (e) {
log("执行中断: " + e.message);
engines.stopAll(); // 停止所有脚本
}
关键注意事项:
- 超时控制:单次验证建议不超过3秒,过长会导致用户体验阻塞
- 降级策略:当连续2次失败时应主动终止,避免无效操作
- Root兼容性:使用
Tap()
前需检查root权限状态:device.isRooted()
补充回答 2
在 Hamibot 自动化脚本中,若遇到 com.startdust.automator.uiobject.child
找不到的问题,通常是由于控件结构、索引越界或布局未完全加载导致的。以下是解决步骤:
1. 确认控件层级关系
- 使用
parent()
获取当前控件的父控件。 - 使用
children()
遍历父控件的所有子控件,检查目标兄弟控件是否存在:// 文档地址 https://docs.hamibot.com/ var target = id("your_target_id").findOne(); var parent = target.parent(); // 获取父控件 var siblings = parent.children(); // 获取所有兄弟控件 siblings.forEach(function(child) { log("子控件类型:" + child.className()); // 根据需求筛选特定控件 if (child.id() === "com.startdust.automator.uiobject.child") { child.click(); // 执行操作 } });
2. 检查子控件索引
- 使用
childCount()
获取子控件总数,避免child(i)
越界:var list = className("AbsListView").findOne(); for (var i = 0; i < list.childCount(); i++) { var child = list.child(i); // 通过索引获取子控件 if (child) { log(child.className()); } else { log("子控件 " + i + " 不存在"); } }
3. 等待控件加载
- 若控件因异步加载未出现,使用
findOne(timeout)
等待:// 最多等待 5 秒 var child = id("com.startdust.automator.uiobject.child").findOne(5000); if (child) { child.click(); } else { toast("未找到目标控件"); }
4. 处理布局变化
- 在滑动或操作后,布局可能重新加载,需重新定位控件:
var parent = id("parent_id").findOne(); parent.scrollForward(); // 滑动后可能触发布局刷新 // 重新获取子控件 var updatedChild = id("com.startdust.automator.uiobject.child").findOne(3000);
5. 兼容性提示
- 避免使用箭头函数(如
() => {}
),改用普通函数。 - 不依赖
child(i)
的直接调用,优先使用children().forEach()
遍历。
常见问题排查:
- 控件不可见:使用
scrollable().scrollForward()
滑动列表。 - 控件属性缺失:通过
id()
、text()
、className()
组合定位。 - 权限问题:确保已开启无障碍服务和前台悬浮窗权限。
如果问题持续,请检查控件的 id
或 className
是否正确,或发送邮件至 support@hamibot.cn
提供详细日志。
ℹ️ 本回答由 AI 生成,内容仅供参考