当前位置: 首页 > 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 例…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

C# 表达式和运算符(求值顺序)

求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如&#xff0c;已知表达式3*52&#xff0c;依照子表达式的求值顺序&#xff0c;有两种可能的结果&#xff0c;如图9-3所示。 如果乘法先执行&#xff0c;结果是17。如果5…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...

恶补电源:1.电桥

一、元器件的选择 搜索并选择电桥&#xff0c;再multisim中选择FWB&#xff0c;就有各种型号的电桥: 电桥是用来干嘛的呢&#xff1f; 它是一个由四个二极管搭成的“桥梁”形状的电路&#xff0c;用来把交流电&#xff08;AC&#xff09;变成直流电&#xff08;DC&#xff09;。…...