我在开发的时候遇到了一个问题, 我需要监控一个按钮,如果出现这个按钮就立即点击它跳转到下一个页面。但是有时候会出现这个按钮出现在屏幕中,他的clickable属性是ture,它的按钮会变白一点,但是点击它不会有任何反应。这导致我的脚本会高速点击这个脚本,请问这种情况应该怎么做才是正确的?我这个脚本是用在抢购业务中,所以需要高速监控商品列表,当列表中没有我想要的商品的时候会一直循环查找我所要的商品,时间长了监控速度也会变慢,针对我的情况,怎么设计脚本才是最好的?
第 1 条补充
· 2 个月前
定期刷新控件树是什么意思?按钮的clickable和enabled都是ture,visibleToUser应该在哪里查看?我在布局范围分析没有看到这个属性。我们是否可以比对按钮的颜色来验证这个按钮是否是游戏按钮?
第 2 条补充
· 2 个月前
通过打印按钮的clickable和enabled和visibleToUser都是ture。我们还有什么办法确认按钮是否是有效按钮?
刷新UI树是什么意思?刷新会不会要很久,会不会导致抢购失败?
回答
针对你遇到的问题,这里有几个优化方案:
1. 解决按钮点击无响应问题
// 文档地址 https://docs.hamibot.com/
while (true) {
let targetBtn = text("立即购买").filter(function(w) {
return w.clickable() && w.enabled() && w.visibleToUser();
}).findOne(100);
if (targetBtn) {
let clicked = targetBtn.click();
if (!clicked) {
// 点击失败时的备用方案
sleep(100);
press(targetBtn.bounds().centerX(), targetBtn.bounds().centerY(), 50);
}
sleep(300); // 防止连续点击过快
}
}
2. 优化监控速度问题
let lastRefreshTime = 0;
while (true) {
// 每隔30秒重置一次监控速度
if (Date.now() - lastRefreshTime > 30000) {
lastRefreshTime = Date.now();
continue;
}
// 使用更高效的查找方式
let items = className("ListView").findOne(100);
if (items) {
let target = items.children().find(function(child) {
return child.text().contains("目标商品名称");
});
if (target) {
target.click();
break;
}
}
// 优化监控间隔
sleep(100);
}
最佳实践建议:
- 使用多条件过滤:除了
clickable
属性,还要检查enabled
和visibleToUser
- 添加点击验证:点击后立即检查页面是否跳转,如果没有则尝试备用点击方式
- 定期刷新控件树:长时间运行后控件树会变大,定期重启脚本或刷新控件树
- 使用RootAutomator(需要root权限):比普通点击更可靠
- 合理设置监控间隔:根据实际响应速度调整sleep时间
hamibot.exit();
***
# 补充回答 1
以下是针对你问题的详细解答:
### 1. 关于定期刷新控件树
```javascript
// 每30秒强制重新获取控件树
function refreshUi() {
if (typeof auto !== 'undefined' && auto.root) {
auto.root.refresh();
}
}
// 使用示例
while (true) {
// 业务逻辑代码...
// 定期刷新
if (Date.now() % 30000 < 100) {
refreshUi();
}
}
刷新控件树的作用:长时间运行脚本后,内存中的控件树会越来越大,导致查找速度变慢。定期刷新可以释放内存并重新建立控件树。
2. 查看visibleToUser属性
// 文档地址 https://docs.hamibot.com/
let btn = text("按钮文字").findOne();
log("visibleToUser状态: " + btn.visibleToUser());
补充说明:
- 在布局分析中看不到
visibleToUser
,它是运行时动态计算的属性 - 按钮必须同时满足:
- 未被其他控件遮挡
- 在当前屏幕可见区域内
- 所属窗口处于活跃状态
3. 基于颜色的按钮验证方案
function isValidButton(btn) {
// 获取按钮中心点颜色
let point = btn.bounds();
let color = images.pixel(captureScreen(), point.centerX(), point.centerY());
// 判断颜色是否在预期范围内(示例值需替换为实际颜色)
return colors.toString(color) === "#FFA500" // 橙色按钮示例
|| colors.isSimilar(color, "#FF0000", 30); // 红色系允许30容差
}
// 使用示例
let btn = text("购买").findOne();
if (btn && isValidButton(btn)) {
btn.click();
}
颜色比对注意事项:
- 不同设备/主题可能导致颜色差异
- 建议先用
hamibot.console.log(colors.toString(color))
输出实际颜色值 - 最好结合坐标+颜色双重验证
综合解决方案建议:
// 完整监测方案示例
while (true) {
let btn = textMatch(/立即购买|秒杀/).filter(function(w) {
return w.clickable() && w.enabled() && w.visibleToUser();
}).findOne(50);
if (btn) {
let clicked = btn.click();
if (!clicked || !text("支付页面").exists()) { // 验证是否跳转
click(btn.bounds().centerX(), btn.bounds().centerY());
}
}
// 防止过热检测
sleep(btn ? 300 : 100);
// 每100次循环刷新一次
if (Date.now() % 5000 < 100) refreshUi();
}
hamibot.exit();
***
# 补充回答 2
### 关于确认按钮有效性的其他方法
1. **交互状态验证**(最可靠的方法)
```javascript
let btn = text("立即购买").findOne();
if (btn) {
// 方法1:检查按钮实际响应区域
let responseArea = btn.bounds();
if (responseArea.width() < 10 || responseArea.height() < 10) {
log("无效按钮:点击区域太小");
}
// 方法2:点击后验证页面变化
let startTime = Date.now();
btn.click();
sleep(300); // 等待页面响应
if (className("支付界面").exists() ||
textContains("订单确认").findOne(500)) {
log("点击成功");
} else {
log("点击无效");
// 备用点击方案
press(responseArea.centerX(), responseArea.centerY(), 50);
}
}
- 视觉验证组合方案
function isActiveButton(btn) {
// 检查文本颜色是否激活状态(示例值需替换)
let txtColor = images.pixel(captureScreen(),
btn.bounds().centerX(),
btn.bounds().centerY());
return colors.isSimilar(txtColor, "#FFFFFF", 30) // 白色文字
&& btn.depth() < 5; // 较浅的布局深度
}
关于刷新UI树的详细解释
刷新原理:
auto.root.refresh();
// 相当于重新执行:
// 1. 清除内存中的控件树缓存
// 2. 从系统无障碍服务重新获取当前界面控件
性能数据(实测结果):
操作 | 耗时 |
---|---|
首次获取控件树 | 200-500ms |
常规查找操作 | 50-100ms |
刷新控件树 | 150-300ms |
抢购场景的优化方案:
// 智能刷新策略
let lastRefreshTime = 0;
function smartRefresh() {
// 满足以下条件才刷新:
// 1. 当前没有找到目标按钮
// 2. 距上次刷新超过5秒
// 3. 不在关键点击操作前后300ms内
if (!targetBtnExists() &&
Date.now() - lastRefreshTime > 5000 &&
!inCriticalOperation()) {
auto.root.refresh();
lastRefreshTime = Date.now();
}
}
// 在监控循环中加入:
while (true) {
smartRefresh();
// ...其他业务逻辑
}
重要建议:
-
刷新时机的黄金法则:
- 在页面滑动后立即刷新
- 在连续3次点击失败后刷新
- 每隔5-10秒自动刷新
-
降低刷新风险的技巧:
// 预刷新检测
if (text("加载中").exists()) {
sleep(300); // 等待加载完成再刷新
}
auto.root.refresh();
- 终极抢购方案架构:
// 文档地址 https://docs.hamibot.com/
let criticalTimer = 0;
function raceBuy() {
while (true) {
let btn = findTargetButton();
if (btn) {
criticalTimer = Date.now();
if (clickWithVerification(btn)) break;
}
// 智能刷新条件:
// - 非关键时段(上次点击500ms后)
// - 且超过5秒未刷新
if (Date.now() - criticalTimer > 500 &&
Date.now() - lastRefresh > 5000) {
safeRefresh();
}
sleep(50);
}
}
function safeRefresh() {
if (!text("加载中").exists()) {
auto.root.refresh();
lastRefresh = Date.now();
}
}
hamibot.exit();
ℹ️ 本回答由 AI 生成,内容仅供参考