当前位置: 首页 > news >正文

【HarmonyOS Next】鸿蒙应用故障处理思路详解

【HarmonyOS Next】鸿蒙应用崩溃处理思路详解

一、崩溃问题发现后定位

1. 崩溃现象:
常见的崩溃问题表现为,应用操作后白屏闪退,或者应用显示无响应卡死。

2.定位问题:
发现崩溃后,我们首先需要了解复现步骤,精确定位复现步骤。因为提供复现步骤得人,可能是用户和测试,非开发人员,其中的步骤并非最短路径。

3.排查问题点
根据复现步骤,我们需要查看日志表现,鸿蒙的DevEco IDE提供了日志看板,根据HiLog和FaultLog,我们可以初步区分崩溃问题的类型。
在这里插入图片描述
根据日志看板的FaultLog,可以查看崩溃输出的

  1. JS Crash,一般是ArkTS原生逻辑的崩溃
  2. CppCrash,一般是NDK,C层的崩溃

JS Crash
点击进入JS Crash中,可以查看到崩溃信息,以下几种类型的错误:
在这里插入图片描述
可以根据JS Crash提示的错误行数,直接点击跳转到错误代码处,根据提示检查和修复问题。

Device info:xxx
Build info:xxx-xxx x.x.x.xxx(xxxx)
Fingerprint:a370fceb59011d96e41e97bda139b1851c911012ab8c386d1a2d63986d6d226d
Module name:com.xxx.xxX
Version:1.0.0
Versioncode:1000000
PreInstalled:No
Foreground:Yes
Pid:39185Uid:20020145
Reason:TypeError
Error name:TypeError
Error message:Cannot read property needRenderTranslate of undefined
Stacktrace:Cannot get SourceMap info, dump raw stack:at anonymous (entry/src/main/ets/pages/Index.ts:49:49)

在这里插入图片描述

this.translationUpY = (this,multiCardsNum >= 1)? sceneContainerSessionListlthis.multiCardsNum -1].needRenderTranslate.translateY :0
this.translationDownY = (this.multiCardsNum >= 2)? sceneContainerSessionList[this.multiCardsNum -
2].needRenderTranslate.translateY :0;

CppCrash
根据日志提示,检查是否有以下错误情况:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

AppFreeze
一般是由于耗时操作,导致堵塞主线程。此时用户操作时,会触发无响应。一般分为以下三种情况,超时时间一般在6s左右。
在这里插入图片描述

内存泄漏
这种问题排查起来是最麻烦的,所以保持良好的代码编程规范,不需要的对象该释放释放,不用的句柄也需要释放。

一般碰到内存泄漏,根据提供的复现步骤,很多情况下是非必现。(如果是必现,那最好了,修复该问题会很快。)我们需要操作复现步骤,使用鸿蒙DevEco IDE的ProFiler工具:
在这里插入图片描述
检测应用操作时的内存使用情况。
在这里插入图片描述

二、问题解决,检查类似错误情况一起修复

1.根据章节一问题定位清楚后,根据错误具体情况,思考修复方案

2.根据问题情况,检查其他代码是否有同类问题,一起修复后验证。

3.根据官网提供的材料进行学习,编码过程中进行规范和排查:
在这里插入图片描述

性能优化举例:
业务场景是:点击跳转下一页,直接加载Web页面。这是大多数三方应用的实现方式,其实应该在后台创建一个ArkWeb组件来预先启动用于渲染的Web渲染进程。这样跳转到web页面的时间就不会那么长:

// 创建NodeController
// common.ets
import { UIContext } from '@kit.ArkUI';
import { webview } from '@kit.ArkWeb';
import { NodeController, BuilderNode, Size, FrameNode } from '@kit.ArkUI';// @Builder中为动态组件的具体组件内容
// Data为入参封装类
class Data {url: string = 'https://www.example.com';controller: WebviewController = new webview.WebviewController();
}
function webBuilder(data: Data) {Column() {Web({ src: data.url, controller: data.controller }).domStorageAccess(true).zoomAccess(true).fileAccess(true).mixedMode(MixedMode.All).width('100%').height('100%').onPageEnd((event) => {// 输出Web页面加载完成时间console.info(`load page end time: ${Date.now()}`);})}
}let wrap = wrapBuilder<Data[]>(webBuilder);// 用于控制和反馈对应的NodeContainer上的节点的行为,需要与NodeContainer一起使用
export class MyNodeController extends NodeController {private rootnode: BuilderNode<Data[]> | null = null;private root: FrameNode | null = null;private rootWebviewController: webview.WebviewController | null = null;// 必须要重写的方法,用于构建节点数、返回节点挂载在对应NodeContainer中// 在对应NodeContainer创建的时候调用、或者通过rebuild方法调用刷新makeNode(uiContext: UIContext): FrameNode | null {console.info(' uicontext is undefined : ' + (uiContext === undefined));if (this.rootnode != null) {const parent = this.rootnode.getFrameNode()?.getParent();if (parent) {console.info(JSON.stringify(parent.getInspectorInfo()));parent.removeChild(this.rootnode.getFrameNode());this.root = null;}this.root = new FrameNode(uiContext);this.root.appendChild(this.rootnode.getFrameNode());// 返回FrameNode节点return this.root;}// 返回null控制动态组件脱离绑定节点return null;}// 当布局大小发生变化时进行回调aboutToResize(size: Size) {console.info('aboutToResize width : ' + size.width + ' height : ' + size.height);}// 当controller对应的NodeContainer在Appear的时候进行回调aboutToAppear() {console.info('aboutToAppear');}// 当controller对应的NodeContainer在Disappear的时候进行回调aboutToDisappear() {console.info('aboutToDisappear');}// 此函数为自定义函数,可作为初始化函数使用// 通过UIContext初始化BuilderNode,再通过BuilderNode中的build接口初始化@Builder中的内容initWeb(url: string, uiContext: UIContext, control: WebviewController) {if (this.rootnode != null) {return;}// 绑定预创建的WebviewControllerthis.rootWebviewController = control;// 创建节点,需要uiContextthis.rootnode = new BuilderNode(uiContext);// 创建动态Web组件this.rootnode.build(wrap, { url: url, controller: control });}// 此函数为自定义函数,可作为初始化函数使用loadUrl(url: string) {if (this.rootWebviewController !== null) {// 复用预创建组件,重新加载urlthis.rootWebviewController.loadUrl(url);}}
}// 创建Map保存所需要的NodeController
let NodeMap: Map<string, MyNodeController | undefined> = new Map();
// 创建Map保存所需要的WebViewController
let controllerMap: Map<string, WebviewController | undefined> = new Map();// 初始化需要UIContext 需在Ability获取
export const createNWeb = (url: string, uiContext: UIContext) => {// 创建NodeControllerlet baseNode = new MyNodeController();let controller = new webview.WebviewController();// 初始化自定义web组件baseNode.initWeb(url, uiContext, controller);controllerMap.set(url, controller);NodeMap.set(url, baseNode);
};// 自定义获取NodeController接口
export const getNWeb = (url: string): MyNodeController | undefined => {// 加载新的Url时,建议复用预创建的Web组件if (!NodeMap.get(url) && NodeMap.get('about://blank')) {// 获取预创建的Web组件let webNode = NodeMap.get('about://blank') as MyNodeController;// 重新加载urlwebNode.loadUrl(url);return webNode;}return NodeMap.get(url);
};

三、思考如何避免问题再次发生,复盘

1.保持好的开发习惯创建踩坑文档,避免自己第二次再发生该问题

2.根据错误情况,分析是否为自己代码逻辑问题,逻辑bug不可避免,只能从开发经验和code review中尽量避免

3.代码容错分支问题,只保证了主流程,未考虑代码错误分支的覆盖情况。这种情况,需要自己吸取教训,避免再次发生。

4.使用检测工具对代码进行扫描,提前规避一些问题:
在这里插入图片描述
5.使用IDE提供的AppAnglyzer生成应用检测报告。根据报告提示,进行修改:
在这里插入图片描述
6.使用鸿蒙提供的DevEco Testing工具,进行稳定性和功耗等测试:
在这里插入图片描述

相关文章:

【HarmonyOS Next】鸿蒙应用故障处理思路详解

【HarmonyOS Next】鸿蒙应用崩溃处理思路详解 一、崩溃问题发现后定位 1. 崩溃现象&#xff1a; 常见的崩溃问题表现为&#xff0c;应用操作后白屏闪退&#xff0c;或者应用显示无响应卡死。 2.定位问题&#xff1a; 发现崩溃后&#xff0c;我们首先需要了解复现步骤&#x…...

狮子座大数据分析(python爬虫版)

十二星座爱情性格 - 星座屋 首先找到一个星座网站&#xff0c;作为基础内容&#xff0c;来获取信息 网页爬取与信息提取 我们首先利用爬虫技术&#xff08;如 Python 中的 requests 与 BeautifulSoup 库&#xff09;获取页面内容。该页面&#xff08;xzw.com/astro/leo/&…...

QT系列教程(18) MVC结构之QItemSelectionModel模型介绍

视频教程 https://www.bilibili.com/video/BV1FP4y1z75U/?vd_source8be9e83424c2ed2c9b2a3ed1d01385e9 QItemSelectionModel Qt的MVC结构支持多个View共享同一个model&#xff0c;包括该model的选中状态等。我们可以通过设置QItemSelectionModel&#xff0c;来更改View的选…...

git设置本地仓库和远程仓库

设置本地仓库和远程仓库是使用Git进行版本控制的基本操作。以下是详细步骤&#xff1a; 创建本地仓库 初始化本地仓库&#xff1a; 打开命令行工具&#xff08;如Terminal或Git Bash&#xff09;。导航到你希望创建Git仓库的项目文件夹。运行以下命令来初始化一个新的Git仓库&…...

openharmony中HDF驱动框架源码梳理-驱动加载流程

要想大概了解一个公司&#xff0c;我们可能只需要知道它的运行逻辑即可&#xff0c;例如我们只需要知道它有财务有研发有运营等&#xff0c;财务报销、研发负责产品等即可&#xff0c;但是如果想深入具体的了解的话我们就要了解都有什么部门(对象)、各部门都包含哪些职责(对象方…...

golang 高性能的 MySQL 数据导出

需求导出方式对比方案1:快照导出(耗时:1.5s)方案2: 偏移分页(耗时:4s)方案 3:普通分页(耗时:4min40s) 需求 导出 MySQL 数据 分析: 一次性 select 大量数据带来的问题 性能问题&#xff1a; 数据库负载&#xff1a;大量数据查询会增加数据库的CPU、内存和I/O负担&#xff…...

31-判断子序列

给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相对位置形成的新字符串。&#xff08;例如&#xff0c;"ace"是"abcde"的一个子序列&#x…...

leetcode日记(95)将有序数组转换为二叉搜索树

很简单&#xff0c;感觉自己越来越适应数据结构题目了…… /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : va…...

使用SSH密钥连接本地git 和 github

目录 配置本地SSH&#xff0c;添加到github首先查看本地是否有SSH密钥生成SSH密钥&#xff0c;和邮箱绑定将 SSH 密钥添加到 ssh-agent&#xff1a;显示本地公钥*把下面这一串生成的公钥存到github上* 验证SSH配置是否成功终端跳转到本地仓库把http协议改为SSH&#xff08;如果…...

C语言基础之【内存管理】

C语言基础之【内存管理】 存储类型作用域普通局部变量静态局部变量普通全局变量静态全局变量全局函数和静态函数 内存布局内存分区存储类型与内存四区内存操作函数memset()memcpy()memmove()memcmp() 堆区内存分配和释放malloc()free() 内存分区代码分析返回栈区地址返回data区…...

C盘清理技巧分享:释放空间,提升电脑性能

目录 1. 引言 2. C盘空间不足的影响 3. C盘清理的必要性 4. C盘清理的具体技巧 4.1 删除临时文件 4.2 清理系统还原点 4.3 卸载不必要的程序 4.4 清理下载文件夹 4.5 移动大文件到其他盘 4.6 清理系统缓存 4.7 使用磁盘清理工具 4.8 清理Windows更新文件 4.9 禁用…...

每天一道算法题【蓝桥杯】【两两交换链表中的节点】

思路 本质问题可以分成若干个子问题 即把前两个链表交换&#xff0c;并与后面的链表相连 故实现函数功能调用自身递归即可 #define _CRT_SECURE_NO_WARNINGS 1 struct ListNode {int val;ListNode *next;ListNode() : val(0), next(nullptr) {}ListNode(int x) : val(x), nex…...

mIoU Class与mIoU Category的区别

mIoU&#xff08;mean Intersection over Union&#xff09;是语义分割任务中常用的评估指标&#xff0c;用于衡量模型预测的分割结果与真实标签之间的重叠程度。mIoU Class 和 mIoU Category 的区别主要体现在计算方式和应用场景上&#xff1a; 1. mIoU Class 定义&#xff…...

深入解析 C 语言中含数组和指针的构造体与共同体内存计算

在 C 语言中&#xff0c;构造体&#xff08;struct&#xff09;和共同体&#xff08;union&#xff09;允许我们将多种数据类型组合到一起。除了常见的基本数据类型之外&#xff0c;经常还会在它们中嵌入数组和指针。由于数组的内存是连续分配的&#xff0c;而指针的大小与平台…...

【C++模板】:开启泛型编程之门(函数模版,类模板)

&#x1f4dd;前言&#xff1a; 在上一篇文章C内存管理中我们介绍了C的内存管理&#xff0c;重点介绍了与C语言的区别&#xff0c;以及new和delete。这篇文章我们将介绍C的利器——模板。 在C编程世界里&#xff0c;模板是一项强大的特性&#xff0c;它为泛型编程奠定了坚实基础…...

HEC-HMS水文建模全解析:气候变化与极端水文、离散化流域单元‌精准刻画地表径流、基流与河道演进过程‌

一、技术革新&#xff1a;数字流域的精密算法革命 在全球气候变化与极端水文事件频发的双重压力下&#xff0c;HEC-HMS模型凭借其‌半分布式建模架构‌与‌多尺度仿真能力‌&#xff0c;已成为现代流域管理的核心工具。该模型通过‌离散化流域单元‌精准刻画地表径流、基流与河…...

具备多种功能的PDF文件处理工具

软件介绍 在日常办公和学习场景中&#xff0c;PDF文件使用极为频繁&#xff0c;而一款功能强大的PDF编辑软件能大幅提升处理效率。 今天要介绍的Adobe Acrobat Pro DC 2024.005.20414&#xff0c;就具备像编辑Word文档一样便捷编辑PDF的能力。 PDF文档在学习和工作中广泛应用…...

【SpringMVC】SpringMVC的启动过程与原理分析:从源码到实战

SpringMVC的启动过程与原理分析&#xff1a;从源码到实战 SpringMVC是Spring框架中用于构建Web应用的核心模块&#xff0c;它基于MVC&#xff08;Model-View-Controller&#xff09;设计模式&#xff0c;提供了灵活且强大的Web开发能力。本文将深入分析SpringMVC的启动过程、核…...

转自南京日报:天洑软件创新AI+仿真技术变制造为“智造

以下文章来源&#xff1a;南京日报 进入3月&#xff0c;南京天洑软件有限公司&#xff08;以下简称天洑软件&#xff09;董事长张明更加忙碌。“公司强调工业软件在数字经济与先进制造业融合中的关键作用&#xff0c;并已广泛应用在能源、电力和航空等领域。”他说&#xff0c;…...

golang dlv调试工具

golang dlv调试工具 在goland2022.2版本 中调试go程序报错 WARNING: undefined behavior - version of Delve is too old for Go version 1.20.7 (maximum supported version 1.19) 即使你go install了新的dlv也无济于事 分析得出Goland实际使用的是 Goland安装目录下dlv 例…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

Spring AOP代理对象生成原理

代理对象生成的关键类是【AnnotationAwareAspectJAutoProxyCreator】&#xff0c;这个类继承了【BeanPostProcessor】是一个后置处理器 在bean对象生命周期中初始化时执行【org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization】方法时…...