本原创文章帖发布在华为开发者联盟社区,欢迎开发者前往访问评论交流,更多与该内容相关讨论,请点击原帖查看:ErrorManager助力高效应对AppFreeze问题:Native崩溃日志的AI辅助定位-华为开发者话题 | 华为开发者联盟
前言
做鸿蒙开发的朋友,大概都收到过这类用户反馈:"点了没反应,但 App 没闪退"。界面像被定格了一样,应用还活着,就是不响应。这种卡住但不崩溃的情况,就是 AppFreeze(应用冻屏)。
传统开发模式下,AppFreeze 问题很难定位——开发者只能靠用户描述加零星日志去"猜",效率很低。HarmonyOS 其实早就考虑到了这个痛点,提供了 ErrorManager 错误管理能力,让应用可以主动感知 AppFreeze 事件并获取现场信息。下面就来看看怎么用。
什么是 AppFreeze
AppFreeze 指的是主线程执行任务时超过 6 秒未响应输入事件或未完成页面刷新,用户感觉界面"卡住"了。和崩溃不同,进程还在,只是主线程被阻塞了。
常见原因就几种:
• 主线程干了耗时操作(同步计算、大量数据序列化等)
• 多线程锁竞争或死锁
• FFRT 任务执行超时
• libuv EventLoop 被阻塞
AppFreeze 发生时系统会生成故障报告,但默认存在本地,开发者没法实时拿到。接下来要介绍的 ErrorManager,就是来解决这个问题的。
ErrorManager 核心能力一览
ErrorManager 在 @kit.AbilityKit 包里,提供的接口与 AppFreeze 相关的主要有这几个:
简单说就是,监听 AppFreeze 和链式处理。
快速接入
第一步:导入模块
import { errorManager } from '@kit.AbilityKit';import { BusinessError } from '@kit.BasicServicesKit';第二步:定义回调
function freezeCallback() { console.error('FreezeHandler', '检测到应用发生冻屏!'); // Get more diagnostic information here // Report to your service quality monitoring platform}第三步:注册监听
Button('开启Freeze监听').onClick(() => { try { errorManager.on('freeze', freezeCallback); console.info('Freeze监听已开启'); } catch (paramError) { let code = (paramError as BusinessError).code; let message = (paramError as BusinessError).message; console.error(`注册失败: ${code}, ${message}`); }});三步完成,应用就具备了 AppFreeze 感知能力。冻屏发生时回调会被触发,里面想做什么都行——存日志、上报监控、尝试恢复都行。
进阶用法:链式处理器
实际业务中可能需要分几步处理:先保存现场,再尝试恢复,最后如果实在不行就退出。setDefaultFreezeObserver 支持链式调用,能实现这种场景。
第一个处理器
let firstHandler: errorManager.FreezeObserver = () => {};const firstFreezeHandler: errorManager.FreezeObserver = () => { console.info('[FirstHandler] 检测到Freeze,开始保存现场...'); // Save diagnostic information locally if (firstHandler) { firstHandler(); // Pass to next handler }};第二个处理器
let secondHandler: errorManager.FreezeObserver = () => {};const secondFreezeHandler: errorManager.FreezeObserver = () => { console.info('[SecondHandler] 尝试恢复应用...'); // Attempt recovery operation if (secondHandler) { secondHandler(); } else { console.info('[SecondHandler] 恢复失败,准备退出'); }};注册
function initFreezeHandlers() { // Later registered handlers are called first errorManager.setDefaultFreezeObserver(firstFreezeHandler); errorManager.setDefaultFreezeObserver(secondFreezeHandler);}AppFreeze 发生时,后注册的处理器先执行——先是 secondHandler 尝试恢复,失败了再调用 firstHandler 保存现场。
配合 loopObserver 预防 Freeze
除了等 AppFreeze 发生,还可以主动监控。loopObserver 能在主线程处理事件超过设定阈值时提前通知,在问题恶化前介入。
let loopObserver: errorManager.LoopObserver = { onLoopTimeOut(timeout: number) { console.warn(`主线程处理超时: ${timeout}ms`); // Issue hasn't worsened yet, early intervention is possible }};// Set threshold to 1000mserrorManager.on('loopObserver', 1000, loopObserver);这个适合做"预防性维护"——主线程开始卡的时候就能发现,不用等到真的 AppFreeze。
最佳实践
1. 尽早注册:在 EntryAbility 的 onCreate 里就注册,避免漏掉早期冻屏事件
2. 回调里同步退出:如果无法恢复,在回调链最后调用 process.processManager.exit(0)退出,别让用户对着黑屏发呆
3. 上报诊断信息:时间、堆栈、环境都上报,形成问题分析的数据基础
4. 阈值合理设置:loopObserver 阈值建议从 1000ms 开始调,太短误报多,太长可能错过最佳干预时机
5. 回调保持轻量:回调里别做复杂 IO 或网络请求,避免连锁反应
常见问题
Q:ErrorManager 和 HiAppEvent 有什么区别?
A:ErrorManager 是同步回调,AppFreeze 发生时会立即通知,适合需要立刻处理的场景;HiAppEvent 更像日志归档,适合离线分析。
Q:AppFreeze 监听会影响性能吗?
A:不会。这是基于系统事件触发的,没有 AppFreeze 发生就不会有任何开销。
Q:能注册多个监听器吗?
A:用 on('freeze')注册的监听器相互独立,都会收到回调;用 setDefaultFreezeObserver 注册的是链式调用,按注册顺序逆序执行。
Q:接口的使用范围和回调的时长?
A:只能在主线程使用,且回调有时间限制,不建议做耗时操作,一般耗时 1s 以内,否则可能会有数据丢失风险。
结语
AppFreeze 是个老问题,但 ErrorManager 给了开发者一件趁手的工具。实时感知、链式处理、提前预警——把这些能力用起来,至少能知道问题出在哪、什么时候发生的。
🔗 官网开发者学堂视频:https://developer.huawei.com/consumer/cn/training/result?type2List=201783644516849879&orderBy=1&courseType=5

🔗 社区 DFX 专题文章: https://developer.huawei.com/consumer/cn/forum/subject/2101218731402391001


【扫码加入 HarmonyOS DFX 技术交流群】





