HarmonyOS NEXT应用开发之异常处理案例

介绍

本示例介绍了通过应用事件打点hiAppEvent获取上一次应用异常信息的方法,主要分为应用崩溃、应用卡死以及系统查杀三种。

效果图预览

使用说明

  1. 点击构建应用崩溃事件,3s之后应用退出,然后打开应用进入应用异常页面,隔1min左右后,显示上次异常退出信息。
  2. 点击构建应用卡死事件,需手动退出,然后打开应用进入应用异常页面,隔1min左右后,显示上次异常退出信息。

实现思路

  1. 构建应用异常。源码参考ApplicationException.ets
 handleOperate(index: number) {switch (index) {case 0:// 在按钮点击函数中构造一个APP_CRASH场景,触发应用崩溃事件let result: object = JSON.parse('');break;case 1:// 在按钮点击函数中构造一个APP_FREEZE场景,触发应用卡死事件,500ms之后执行无限循环while (true) {}}}
  1. 应用退出后,进入本页面,等待订阅消息通知,待收到订阅消息后,通过EventSubscription.ets中的onReceive函数,接收到异常信息数据, 并通过AppStorage.setOrCreate(‘appEventGroups’,异常信息数据)双向绑定异常信息,源码参考代码可参考EventSubscription.ets
import hiAppEvent from '@ohos.hiviewdfx.hiAppEvent';
import { logger } from '@ohos/base';const TAG: string = 'eventSubscription';export function eventSubscription() {// 添加应用事件观察者方法,可用于订阅应用事件hiAppEvent.addWatcher({// 开发者可以自定义观察者名称,系统会使用名称来标识不同的观察者name: "mst",// 开发者可以订阅感兴趣的系统事件,此处是订阅了崩溃事件appEventFilters: [{domain: hiAppEvent.domain.OS,names: [hiAppEvent.event.APP_CRASH, hiAppEvent.event.APP_FREEZE]}],// TODO:知识点:获取事件组信息。开发者可以自行实现订阅实时回调函数,以便对订阅获取到的事件数据进行自定义处理onReceive: async (domain: string, appEventGroups: Array<hiAppEvent.AppEventGroup>) => {logger.info(TAG, `HiAppEvent onReceive: domain=${domain}`);// 获取事件组信息,与ApplicationException文件中的@StorageLink('faultMessage') faultMessage进行双向数据绑定AppStorage.setOrCreate('appEventGroups', appEventGroups);}});
}
  1. @StorageLink(‘appEventGroups’)接收订阅事件函数传递的事件组信息,调用getFaultMessage函数对信息进行处理,将处理后的信息通过 this.faultDataSource.pushData(message) 添加到懒加载数据源中,并通过this.faultDataSource.persistenceStorage()执行持久化存储,最后通过使用LazyForEach将数据信息加载到页面上。 具体源码参考ApplicationException.ets
@Component
struct FaultArea {// 懒加载数据源@State faultDataSource: FaultDataSource = new FaultDataSource();// 双向数据绑定懒加载数据源的数组长度@StorageLink('faultDataSourceLength') faultDataSourceLength: number = 0;// 双向数据绑定事件组,与AppStorage.setOrCreate进行绑定,此变量发生变化触发getFaultMessage函数@StorageLink('appEventGroups') @Watch('getFaultMessage') appEventGroups: Array<hiAppEvent.AppEventGroup> = [];@Consume eventIndex: number;async aboutToAppear() {logger.info(TAG, `aboutToAppear start`);// 获取Preferences实例PreferencesManager.getPreferences(this.faultDataSource);}// 获取应用异常信息async getFaultMessage() {logger.info(TAG, `getAppEventGroups start`);if (this.appEventGroups && this.appEventGroups.length > 0) {// 遍历事件组this.appEventGroups.forEach((eventGroup: hiAppEvent.AppEventGroup) => {// 遍历事件对象集合eventGroup.appEventInfos.forEach(async (eventInfo: hiAppEvent.AppEventInfo) => {let message: string = '';message += `HiAppEvent eventInfo.domain=${eventInfo.domain}\n` // 事件领域+ `HiAppEvent eventInfo.name=${eventInfo.name}\n`  // 事件名称+ `HiAppEvent eventInfo.eventType=${eventInfo.eventType}\n` // 事件名称+ `HiAppEvent eventInfo.params.time=${eventInfo.params['time']}\n` // 事件发生的时间+ `HiAppEvent eventInfo.params.crash_type=${eventInfo.params['crash_type']}\n`+ `HiAppEvent eventInfo.params.foreground=${eventInfo.params['foreground']}\n`+ `HiAppEvent eventInfo.params.bundle_version=${eventInfo.params['bundle_version']}\n`+ `HiAppEvent eventInfo.params.bundle_name=${eventInfo.params['bundle_name']}\n`+ `HiAppEvent eventInfo.params.exception=${JSON.stringify(eventInfo.params['exception'])}\n`+ `HiAppEvent eventInfo.params.hilog.size=${eventInfo.params['hilog'].length}\n`;// TODO:知识点:将异常信息存储到数组faultMessage当中this.faultDataSource.pushData(message);})})}// TODO:知识点:持久化存储异常信息集合this.faultDataSource.persistenceStorage();}build() {List() {// 添加判断,如果异常信息集合的信息条数大于0,遍历异常信息if (this.faultDataSourceLength > 0) {// 性能:动态加载数据场景可以使用LazyForEach遍历数据。https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/arkts-rendering-control-lazyforeach-0000001524417213-V3LazyForEach(this.faultDataSource, (message: string) => {ListItem() {Text(message).textAlign(TextAlign.Start)}}, (item: string) => item)} else {ListItem() {// 根据被点击事件的下标响应指定的信息Text(this.eventIndex === 0 ? $r('app.string.crash_event_message') :(this.eventIndex === 1 ? $r('app.string.freeze_event_message') :(this.faultSign ? $r('app.string.data_delay_toast') :$r('app.string.no_message'))))}}}.width('92%').height(300).shadow(ShadowStyle.OUTER_DEFAULT_SM).borderRadius($r('app.string.ohos_id_corner_radius_default_m')).padding($r('app.string.ohos_id_card_padding_start'))}
}
  1. 以上代码中有引用懒加载数据类和持久化存储类,源码可参考DataSource.ets和 PreferencesManager.ets。
// DataSource.ets
export class FaultDataSource extends BasicDataSource {// 懒加载数据private faultMessage: Array<string> = [];// TODO:知识点:获取懒加载数据源的数据长度totalCount(): number {return this.faultMessage.length;}// 获取指定数据项getData(index: number): string {return this.faultMessage[index];}// TODO:知识点:存储数据到懒加载数据源中pushData(data: string): void {this.faultMessage.push(data);// 在数组头部添加数据this.notifyDataAdd(this.faultMessage.length - 1);AppStorage.setOrCreate('faultDataSourceLength', this.totalCount());}// TODO:知识点:持久化存储异常信息集合persistenceStorage(): void {PreferencesManager.putFaultMessage(this.faultMessage);}
}// PreferencesManager.ets/*** 存储数据异常信息* @param faultMessage 异常信息集合*/public static putFaultMessage(faultMessage: Array<string>) {logger.info(`putMessage start`);try {// TODO:知识点:通过 dataPreferencesManager.put方法存储数据dataPreferencesManager.put('faultMessage', JSON.stringify(faultMessage), async (err: BusinessError) => {if (err) {logger.error("Failed to put value of 'faultMessage'. code =" + err.code + ", message =" + err.message);return;}logger.info('Succeeded in putting value of faultMessage.');dataPreferencesManager.flush();})} catch (err) {let code = (err as BusinessError).code;let message = (err as BusinessError).message;logger.error("Failed to put value of 'catch err'. code =" + err.code + ", message =" + err.message);}}/*** 获取数据异常信息* @param faultMessage 异常信息集合*/public static getFaultMessage(faultDataSource:FaultDataSource) {logger.info(`getFaultMessage start`);try {// TODO:知识点:通过dataPreferencesManager.get方法获取异常信息数据let promise = dataPreferencesManager.get('faultMessage', []);promise.then(async (data: dataPreferences.ValueType) => {if (typeof data === 'string') {let faultData: Array<string> = JSON.parse(data);// 将异常数据添加到懒加载数据源中faultData.forEach((item: string) => {faultDataSource.pushData(item);})// 双向数据绑定懒加载数据源长度,更新数据源长度AppStorage.setOrCreate('faultDataSourceLength',faultDataSource.totalCount())logger.info('Succeeded in getting value of faultMessage.');}})} catch (err) {logger.error("Failed to get value of 'catch err'. code =" + err.code + ", message =" + err.message);}}

高性能知识点

本示例使用了LazyForEach进行数据懒加载,将叠加获取到的应用异常信息进行渲染。

工程结构&模块类型

aplicationexception                             // har类型
|---model
|   |---DataSource.ets                          // 模型层-懒加载数据源
|   |---EventSubscription.ets                   // 数据模型层-订阅应用事件
|   |---MockData.ets                            // 数据模型层-模拟数据
|   |---PreferencesManager.ets                  // 数据模型层-持久化存储
|---view
|   |---PreferencesManager.ets                  // 视图层-应用异常页面

模块依赖

本实例依赖common模块来实现日志的打印、资源的调用以及公共组件FunctionDescription的引用。

参考资料

应用事件打点HiAppEvent 数据懒加载LazyForEach

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:https://qr21.cn/FV7h05

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

大厂鸿蒙面试题:https://qr21.cn/FV7h05

鸿蒙开发面试大盘集篇(共计319页):https://qr21.cn/FV7h05

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/742982.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nginx启动闪退

在nginx目录下cmd&#xff0c;nginx -t&#xff0c;找到原因是&#xff1a;“在端口80上运行NGINX时&#xff0c;因为端口80是HTTP默认端口&#xff0c;需要管理员权限才能访问” 所以修改端口号&#xff1a; 在nginx.conf文件中&#xff0c;修改listen&#xff1a;80为8080 …

【C++】类的默认成员函数(下)

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、运算符重载1.1 引例1.2 概念及运用&#xff1a;1.3 牛刀小试:1.4 重载1.5 运…

Python网络基础爬虫-python基本语法

文章目录 逻辑语句if,else,elifforwhile异常处理 函数与类defpassclass 逻辑语句 熟悉C/C语言的人们可能很希望Python提供switch语句&#xff0c;但Python中并没有这个关键词&#xff0c;也没有这个语句结构。但是可以通过if-elif-elif-…这样的结构代替&#xff0c;或者使用字…

目标检测——YOLOv2算法解读

论文&#xff1a;YOLO9000: Better, Faster, Stronger 作者&#xff1a;Joseph Redmon, Ali Farhadi 链接&#xff1a;https://arxiv.org/pdf/1612.08242v1.pdf 代码&#xff1a;http://pjreddie.com/yolo9000/ YOLO系列其他文章&#xff1a; YOLOv1通俗易懂版解读SSD算法解读…

记一次生产慢sql索引优化及思考

记一次生产慢sql索引优化及思考 问题重现 夜黑风高的某一晚&#xff0c;突然收到一条运营后台数据库慢sql的报警&#xff0c;耗时竟然达到了60s。看了一下&#xff0c;还好不是很频繁&#xff0c;内心会更加从容排查问题&#xff0c;应该是特定条件下没有走到索引导致&#x…

[论文精读]Dynamic Coarse-to-Fine Learning for Oriented Tiny Object Detection

论文网址&#xff1a;[2304.08876] 用于定向微小目标检测的动态粗到细学习 (arxiv.org) 论文代码&#xff1a;https://github.com/ChaselTsui/mmrotate-dcfl 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&…

支付模块-基于消息队列发送支付通知消息

消息队列发送支付通知消息 需求分析 订单服务作为通用服务&#xff0c;在订单支付成功后需要将支付结果异步通知给其他对接的微服务&#xff0c;微服务收到支付结果根据订单的类型去更新自己的业务数据 技术方案 使用消息队列进行异步通知需要保证消息的可靠性即生产端将消息…

深入了解 大语言模型(LLM)微调方法

引言 众所周知&#xff0c;大语言模型(LLM)正在飞速发展&#xff0c;各行业都有了自己的大模型。其中&#xff0c;大模型微调技术在此过程中起到了非常关键的作用&#xff0c;它提升了模型的生成效率和适应性&#xff0c;使其能够在多样化的应用场景中发挥更大的价值。 那么&…

服务器命令

服务器命令 服务器命令top查看任务 服务器命令 top查看任务 、ps 命令 ps 命令是最基本同时也是非常强大的进程查看命令。使用该命令可以确定有哪些进程正在运行和它所运行的状态、进程是否结束、进程有没有僵死、哪些进程占用了过多的资源等。总之大部分信息都是可以通过执行…

pytorch模型转onnx格式,编写符号函数实现torch算子接口和onnx算子的映射,新建简单算子--模型部署记录整理

对于深度学习模型来说&#xff0c;模型部署指让训练好的模型在特定环境中运行的过程。相比于软件部署&#xff0c;模型部署会面临更多的难题&#xff1a; 运行模型所需的环境难以配置。深度学习模型通常是由一些框架编写&#xff0c;比如 PyTorch、TensorFlow。由于框架规模、依…

掌握Go语言:深入encoding/gob包的高效数据序列化

掌握Go语言&#xff1a;深入encoding/gob包的高效数据序列化 引言理解Gob和它的使用场景Gob的概念和设计目标Gob的适用场景和优势 开始使用Gob基本的Gob编码和解码示例代码编码&#xff08;序列化&#xff09;解码&#xff08;反序列化&#xff09; Gob编码高级应用自定义类型的…

【Java语言】遍历List元素时删除集合中的元素

目录 前言 实现方式 1.普通实现 1.1 使用【for循环】 方式 1.2 使用【迭代器】方式 2.jdk1.8新增功能实现 2.1 使用【lambda表达式】方式 2.2 使用【stream流】方式 注意事项 1. 使用【for循环】 方式 2. 不能使用增强for遍历修改元素 总结 前言 分享几种从List中移…

基于 K8s 容器集群的容灾架构与方案

作者&#xff1a;庄宇 在设计系统架构时&#xff0c;我们必须假设任何组件和任何基础设施可能会在任何时间失效&#xff0c;例如&#xff1a;自然灾害&#xff0c;电力中断&#xff0c;网络中断&#xff0c;错误的系统变更等。为了应对挑战&#xff0c;我们必须设计合适的容灾…

在centos8中部署Tomcat和Jenkins

参考链接&#xff1a;tomcat安装和部署jenkins_jenkins和tomcat-CSDN博客 1、进入centos中 /usr/local 目录文件下 [rootlocalhost webapps]# cd /usr/local2、使用通过wget命令下下载tomcat或者直接在官网下载centos版本的包后移动到centos中的local路径下 3、下载tomcat按…

VUE3内置组件Transition的学习使用

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 更多nbcio-boot功能请看演示系统RuoYi-Nbcio亿事达企业管理平台 gitee源代码地址 后端代码&#xff1a;…

详解Postman使用

简介&#xff1a; 1.简介 PostMan&#xff0c;一款接口调试工具。 特点&#xff1a; 可以保留接口请求的历史记录 可以使用测试集Collections有效管理组织接口 可以在团队之间同步接口数据 1.简介 PostMan&#xff0c;一款接口调试工具。 特点&#xff1a; 可以保留接口请求…

从0到1入门C++编程——12 演讲比赛流程管理系统

文章目录 一、创建类并显示菜单二、退出管理系统三、开始演讲比赛四、查看往届记录五、清空比赛记录六、案例源代码 演讲比赛流程管理系统 比赛规则&#xff1a;演讲比赛共有12个人参加&#xff0c;比赛分两轮进行&#xff0c;第一轮为淘汰赛&#xff0c;第二轮为决赛。每名选手…

HTML万字学习总结

html文本标签特殊符号图片音频与视频超链接表单列表表格语义标签(布局) html文本标签 标签简介根目录规定文档相关的配置信息&#xff08;元数据元素表示文档的内容表示那些不能由其它 HTML 元相关元素&#xff08;(<base>、<link>, <script>、<style>…

今日AI:GPT-4.5意外曝光可能6月发布、UP主借AI识别情绪播放量186万、全球首个AI程序员诞生

欢迎来到【今日AI】栏目!这里是你每天探索人工智能世界的指南&#xff0c;每天我们为你呈现AI领域的热点内容&#xff0c;聚焦开发者&#xff0c;助你洞悉技术趋势、了解创新AI产品应用。 新鲜AI产品点击了解:AIbase - 智能匹配最适合您的AI产品和网站 &#x1f4e2;一分钟速…

如何拆解技术瓶颈的难点

以大化小的思路 解决一个一个小问题从而解决最终问题 三段论&#xff1a; 抽象能力 职责领域划分 分层构建解决方案 案例&#xff1a;全局分布式事务的解决方案 抽象能力&#xff1a;全局分布式 是由一个个小的事务组合而成的&#xff0c;其中一个分布式事务出现问题&#xff…