var window = null
var taskThreads = null
function init() {
window = floaty.rawWindow(
<vertical w='140dp' h='240dp' padding='8dp' bg='#80000000' id='container'>
<button w='50dp' h='40dp' bg='#03E06D' text='测试' textSize='14sp' textColor='#000000' id='btn1' />
</vertical>
)
// 设置悬浮窗属性
window.setPosition(0, 100)
window.setSize(200, 800)
}
function ceshi(callback) {
console.log('ceshi 执行中...');
setTimeout(() => {
callback(111)
}, 1000)
}
window.btn1.click(() => {
// 按钮1的点击事件
taskThreads = threads.start(function () {
console.log('点击我了');
ceshi()
})
// console.log('点击我了');
// function handle(num){
// console.log('handle 执行中...',num);
// }
// ceshi(handle)
})
main();
setInterval(() => {
if(taskThreads){
if(taskThreads.isAlive()){
console.log(1111);
}
}
}, 1000);
这样的脚本为什么 会出现 hamibot被退出的情况呢 时间不确定 有时候只能挂四五分钟 就被退出了 有时候能挂一个小时
回答
// 文档地址 https://docs.hamibot.com/
你的脚本出现 Hamibot 被退出(崩溃或自动停止)的情况,主要问题出在 JavaScript 引擎 Rhino 的兼容性问题 和 异步回调中的线程安全问题 上。下面我来详细分析原因并提供修复方案。
❌ 问题分析
1. 箭头函数不被完全支持
你使用了 () => {} 箭头函数:
setTimeout(() => {
callback(111)
}, 1000)
⚠️ Hamibot 使用的是 Rhino 1.7.15 JavaScript 引擎,不支持 ES6 的箭头函数表达式。虽然部分语法可能能运行,但在某些设备或环境下会导致解析失败、异常退出甚至直接崩溃。
2. 未传入回调函数导致 runtime error
你在点击事件中调用了:
ceshi()
但 ceshi(callback) 函数需要一个回调参数 callback,而你没有传入。
这会触发:
callback(111) // TypeError: Cannot call method 'call' of undefined
这种错误在非 UI 线程中抛出且未捕获时,可能导致脚本崩溃,严重时会引发 Hamibot 整体退出。
3. 多线程与日志输出冲突(潜在风险)
你在 threads.start() 中执行逻辑,并频繁使用 console.log。如果多个线程同时写入日志,在低性能设备上可能会引起资源争用或缓冲区溢出,增加崩溃概率。
✅ 正确写法(兼容 Rhino 并避免崩溃)
// 文档地址 https://docs.hamibot.com/
var window = null;
var taskThreads = null;
function init() {
// 创建原始悬浮窗
window = floaty.rawWindow(
<vertical w='140dp' h='240dp' padding='8dp' bg='#80000000' id='container'>
<button w='50dp' h='40dp' bg='#03E06D' text='测试' textSize='14sp' textColor='#000000' id='btn1' />
</vertical>
);
// 设置位置和大小
window.setPosition(0, 100);
// 注意:setSize 接收像素值,这里建议用实际 px 或保持 dp 自动转换
// 若想设置为固定 dp,可使用 device.widthFactor 等换算,否则直接使用数字即可
window.setSize(-2, -2); // 自适应内容大小,推荐
}
function ceshi(callback) {
console.log('ceshi 执行中...');
setTimeout(function () {
if (typeof callback === 'function') {
callback(111);
}
}, 1000);
}
// 初始化
init();
// 按钮点击监听
window.btn1.click(function () {
console.log('点击我了');
// 启动新线程
taskThreads = threads.start(function () {
ceshi(function (num) {
console.log('handle 执行中... ', num);
});
});
});
// 定期检查线程状态
setInterval(function () {
if (taskThreads) {
if (taskThreads.isAlive()) {
console.log("当前任务线程正在运行");
} else {
console.log("任务线程已结束");
}
}
}, 1000);
// 主循环防止脚本退出
hamibot.autoKeepRunning();
🔧 关键修改说明
| 修改点 | 原因 |
|---|---|
将 () => {} 改为 function () {} |
兼容 Rhino 1.7.15,避免语法错误 |
给 ceshi() 正确传入回调函数 |
防止 callback is undefined 错误 |
添加 typeof callback === 'function' 判断 |
更安全的调用方式 |
调用 hamibot.autoKeepRunning() |
保证脚本持续运行,防止主流程结束导致退出 |
💡 建议最佳实践
-
永远不要使用 ES6+ 语法
如:箭头函数、let/const、模板字符串、解构赋值等。 -
所有 UI 操作必须通过
ui.run()更新
当前例子没涉及动态修改 UI,但如果要改文本、隐藏按钮等,请使用: