HarmonyOS 应用调试实战指南:从错误日志到代码修复


正常编译
引言
在 HarmonyOS 应用开发过程中,调试是不可或缺的环节。当应用崩溃时,开发者需要从错误日志中快速定位问题,分析根本原因,并实施有效的修复方案。
本文以一个真实的 TypeError: Cannot read property length of undefined 错误为例,详细介绍从错误分析到代码修复的完整流程,帮助开发者掌握 HarmonyOS 应用调试的核心技能。
一、错误日志深度剖析
1.1 错误日志结构分析
当应用崩溃时,HarmonyOS 会生成详细的错误日志。让我们分析一个典型的错误日志:
Device info:emulator
Build info:emulator 6.1.0.125(SP9DEVC00E120R4P11)
DeviceDebuggable:No
Fingerprint:942faf326339d918a897afacb207c06b5f2247f32921abfa70b25f5c5701fe9b
Timestamp:2026-06-11 20:59:14.748
Module name:com.shili.myapplication
ReleaseType:debug
CpuAbi:x86_64
Version:1.0.0
VersionCode:1000000
IsSystemApp:No
PreInstalled:No
Foreground:Yes
Pid:28084
Uid:20020065
Process life time:16s
Process Memory(kB): 161116(Rss)
Device Memory(kB): Total 4025356, Free 1892684, Available 2549308
Page switch history:
20:59:14.547 :enters foreground
Reason:TypeError
Error name:TypeError
Error message:Cannot read property toString of undefined
Stacktrace:
at anonymous entry (entry/src/main/ets/pages/Index.ets:339:42)
at updateFunc (/usr1/hmos_for_system/src/increment/sourcecode/out/generic_generic_x86_64only/all_all_phone_standard_emulator/obj/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/stateMgmt.js:9479:1)
at observeComponentCreation2 (/usr1/hmos_for_system/src/increment/sourcecode/out/generic_generic_x86_64only/all_all_phone_standard_emulator/obj/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/stateMgmt.js:9509:1)
at OverviewTab entry (entry/src/main/ets/pages/Index.ets:332:15)
at anonymous entry (entry/src/main/ets/pages/Index.ets:301:9)
at ifElseBranchUpdateFunction (/usr1/hmos_for_system/src/increment/sourcecode/out/generic_generic_x86_64only/all_all_phone_standard_emulator/obj/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/stateMgmt.js:5220:1)
at anonymous entry (entry/src/main/ets/pages/Index.ets:300:34)
at updateFunc (/usr1/hmos_for_system/src/increment/sourcecode/out/generic_generic_x86_64only/all_all_phone_standard_emulator/obj/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/stateMgmt.js:9479:1)
at observeComponentCreation2 (/usr1/hmos_for_system/src/increment/sourcecode/out/generic_generic_x86_64only/all_all_phone_standard_emulator/obj/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/stateMgmt.js:9509:1)
at initialRender entry (entry/src/main/ets/pages/Index.ets:297:56)
at initialRenderView (/usr1/hmos_for_system/src/increment/sourcecode/out/generic_generic_x86_64only/all_all_phone_standard_emulator/obj/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/stateMgmt.js:9004:1)
1.2 关键信息提取
从日志中提取关键信息:
| 字段 | 值 | 说明 |
|---|---|---|
| 错误类型 | TypeError | JavaScript 运行时错误 |
| 错误信息 | Cannot read property toString of undefined | 尝试读取 undefined 的 toString 属性 |
| 发生位置 | Index.ets:339:42 | 第 339 行,第 42 列 |
| 调用栈 | OverviewTab → build() → initialRender | 渲染流程中发生 |
| 进程状态 | Foreground:Yes | 应用在前台运行 |
| 内存状态 | Available 2549308 kB | 内存充足,非内存问题 |
1.3 调用栈分析
调用栈提供了错误发生的完整上下文:
initialRenderView
↓
initialRender entry (Index.ets:297:56)
↓
anonymous entry (Index.ets:300:34)
↓
ifElseBranchUpdateFunction
↓
anonymous entry (Index.ets:301:9)
↓
OverviewTab entry (Index.ets:332:15)
↓
anonymous entry (Index.ets:339:42) ← 错误发生位置
这表明错误发生在 OverviewTab 组件的渲染过程中,具体是第 339 行。
二、代码定位与问题分析
2.1 定位错误代码
根据日志中的位置信息,查看第 339 行代码:
// Index.ets 第 339 行
Text('基于 ' + this.doneCheckups.toString() + '/' + this.totalCheckups.toString() + ' 项体检完成率 与 ' + this.normalMetrics.toString() + '/' + HEALTH_METRICS.length.toString() + ' 项指标正常率')
2.2 分析可能的原因
从代码中可以看到,该行使用了多个 getter:
| getter | 用途 | 可能返回 undefined 的原因 |
|---|---|---|
this.doneCheckups |
已完成的体检项目数 | getter 在 build() 中无法被正确追踪 |
this.totalCheckups |
体检项目总数 | 同上 |
this.normalMetrics |
正常的健康指标数 | 同上 |
2.3 验证假设
为了验证假设,我们需要查看这些 getter 的定义:
get doneCheckups(): number {
let cnt: number = 0
for (let i = 0; i < CHECKUP_ITEMS.length; i++) {
if (CHECKUP_ITEMS[i].done) cnt++
}
return cnt
}
get totalCheckups(): number {
return CHECKUP_ITEMS.length
}
get normalMetrics(): number {
let cnt: number = 0
for (let i = 0; i < HEALTH_METRICS.length; i++) {
if (HEALTH_METRICS[i].status === '正常') cnt++
}
return cnt
}
这些 getter 在普通 JavaScript 环境中可以正常工作,但在 ArkTS 声明式 UI 的 build() 函数中会返回 undefined。
2.4 根本原因分析
核心问题:ArkTS 的状态管理系统在编译时进行依赖分析,只能识别 @State、@Prop、@Link 等装饰器修饰的变量。getter 函数内部的状态访问无法被追踪,导致在组件初始化时返回 undefined。
┌─────────────────────────────────────────────────────────────┐
│ ArkTS 编译时依赖分析 │
├─────────────────────────────────────────────────────────────┤
│ build() { │
│ // ✅ 可追踪:直接访问 @State 变量 │
│ Text(this.filterCategory) │
│ │
│ // ❌ 不可追踪:getter 内部访问 │
│ Text(this.filteredCheckups.length.toString()) │
│ // 编译器只能看到 this.filteredCheckups, │
│ // 无法知道内部依赖了哪些状态 │
│ } │
└─────────────────────────────────────────────────────────────┘
三、解决方案设计与实现
3.1 方案设计原则
在设计解决方案时,遵循以下原则:
| 原则 | 说明 |
|---|---|
| 最小侵入性 | 尽量保持原有代码结构,最小化改动 |
| 可维护性 | 代码易于理解和维护 |
| 性能优化 | 避免不必要的重复计算 |
| 类型安全 | 保持 TypeScript 的类型检查 |
3.2 核心解决方案
将 getter 转换为 @State 变量 + update 方法的模式:
// ====== 方案对比 ======
// ❌ 原方案(问题代码)
@Entry
@Component
struct HealthApp {
@State filterCategory: string = '全部'
get filteredCheckups(): CheckupItem[] {
let result: CheckupItem[] = []
for (let i = 0; i < CHECKUP_ITEMS.length; i++) {
if (this.filterCategory !== '全部' && CHECKUP_ITEMS[i].category !== this.filterCategory) continue
result.push(CHECKUP_ITEMS[i])
}
return result
}
build() {
Column() {
Text('共 ' + this.filteredCheckups.length.toString() + ' 项') // ❌ undefined
}
}
}
// ✅ 优化方案
@Entry
@Component
struct HealthApp {
@State filterCategory: string = '全部'
@State filteredCheckups: CheckupItem[] = [] // ✅ 状态变量
updateFilteredCheckups(): void { // ✅ 更新方法
let result: CheckupItem[] = []
for (let i = 0; i < CHECKUP_ITEMS.length; i++) {
if (this.filterCategory !== '全部' && CHECKUP_ITEMS[i].category !== this.filterCategory) continue
result.push(CHECKUP_ITEMS[i])
}
this.filteredCheckups = result // ✅ 直接赋值触发更新
}
aboutToAppear(): void {
this.updateFilteredCheckups() // ✅ 初始化时调用
}
build() {
Column() {
Text('共 ' + this.filteredCheckups.length.toString() + ' 项') // ✅ 正常工作
}
}
}
3.3 完整实现步骤
步骤 1:识别所有问题 getter
在代码中查找所有在 build() 中使用的 getter:
// 需要转换的 getter 列表
get filteredCheckups(): CheckupItem[] { ... }
get filteredTips(): HealthTip[] { ... }
get healthScore(): number { ... }
get scoreLevel(): string { ... }
get scoreColor(): string { ... }
get totalCheckups(): number { ... }
get doneCheckups(): number { ... }
get normalMetrics(): number { ... }
get seasonOrder(): string[] { ... }
步骤 2:添加 @State 变量
将每个 getter 转换为 @State 变量:
@Entry
@Component
struct HealthApp {
// 原有状态
@State currentTab: number = 0
@State filterCategory: string = '全部'
@State selectedTipSeason: string = '全年'
@State showCompleted: boolean = true
@State selectedCheckupId: number = -1
// 新增状态变量(替代 getter)
@State filteredCheckups: CheckupItem[] = []
@State filteredTips: HealthTip[] = []
@State healthScore: number = 0
@State scoreLevel: string = '一般'
@State scoreColor: string = '#F39C12'
@State totalCheckups: number = 0
@State doneCheckups: number = 0
@State normalMetrics: number = 0
@State seasonOrder: string[] = ['春', '夏', '秋', '冬', '全年']
}
步骤 3:创建 update 方法
将 getter 的计算逻辑转换为 update 方法:
updateFilteredCheckups(): void {
let result: CheckupItem[] = []
for (let i = 0; i < CHECKUP_ITEMS.length; i++) {
let item: CheckupItem = CHECKUP_ITEMS[i]
if (this.filterCategory !== '全部' && item.category !== this.filterCategory) continue
if (!this.showCompleted && item.done) continue
result.push(item)
}
this.filteredCheckups = result
}
updateFilteredTips(): void {
let result: HealthTip[] = []
for (let i = 0; i < HEALTH_TIPS.length; i++) {
let tip: HealthTip = HEALTH_TIPS[i]
if (this.selectedTipSeason === '全年') {
result.push(tip)
} else if (tip.season === this.selectedTipSeason || tip.season === '全年') {
result.push(tip)
}
}
this.filteredTips = result
}
updateHealthScore(): void {
// 计算统计数据
this.totalCheckups = CHECKUP_ITEMS.length
let doneCnt: number = 0
for (let i = 0; i < CHECKUP_ITEMS.length; i++) {
if (CHECKUP_ITEMS[i].done) doneCnt++
}
this.doneCheckups = doneCnt
let normalCnt: number = 0
for (let i = 0; i < HEALTH_METRICS.length; i++) {
if (HEALTH_METRICS[i].status === '正常') normalCnt++
}
this.normalMetrics = normalCnt
// 计算健康分
let doneRatio: number = this.doneCheckups / this.totalCheckups
let normalRatio: number = this.normalMetrics / HEALTH_METRICS.length
let score: number = Math.round(doneRatio * 40 + normalRatio * 60)
if (score < 0) score = 0
if (score > 100) score = 100
this.healthScore = score
// 设置等级和颜色
if (score >= 90) {
this.scoreLevel = '优秀'
this.scoreColor = '#2ECC71'
} else if (score >= 75) {
this.scoreLevel = '良好'
this.scoreColor = '#3498DB'
} else if (score >= 60) {
this.scoreLevel = '一般'
this.scoreColor = '#F39C12'
} else {
this.scoreLevel = '需关注'
this.scoreColor = '#E74C3C'
}
}
步骤 4:初始化调用
在 aboutToAppear() 生命周期方法中调用所有 update 方法:
aboutToAppear(): void {
this.updateFilteredCheckups()
this.updateFilteredTips()
this.updateHealthScore()
}
步骤 5:事件处理更新
在所有状态变化的事件处理函数中调用对应的 update 方法:
// 分类筛选变化
onCategoryChange(cat: string): void {
this.filterCategory = cat
this.selectedCheckupId = -1
this.updateFilteredCheckups() // ✅ 更新筛选结果
}
// 显示/隐藏已完成切换
onShowCompletedToggle(): void {
this.showCompleted = !this.showCompleted
this.selectedCheckupId = -1
this.updateFilteredCheckups() // ✅ 更新筛选结果
}
// 季节筛选变化
onSeasonChange(season: string): void {
this.selectedTipSeason = season
this.updateFilteredTips() // ✅ 更新贴士列表
}
3.4 代码优化与重构
优化 1:提取公共方法
将重复的遍历逻辑提取为公共方法:
filterArray<T>(source: T[], filterFn: (item: T) => boolean): T[] {
let result: T[] = []
for (let i = 0; i < source.length; i++) {
if (filterFn(source[i])) {
result.push(source[i])
}
}
return result
}
updateFilteredCheckups(): void {
this.filteredCheckups = this.filterArray(CHECKUP_ITEMS, (item: CheckupItem) => {
if (this.filterCategory !== '全部' && item.category !== this.filterCategory) return false
if (!this.showCompleted && item.done) return false
return true
})
}
优化 2:批量更新优化
当多个状态同时变化时,合并更新以减少渲染次数:
resetFilters(): void {
// 批量修改状态
this.filterCategory = '全部'
this.showCompleted = true
this.selectedTipSeason = '全年'
// 一次性更新所有计算状态
this.updateFilteredCheckups()
this.updateFilteredTips()
this.updateHealthScore()
}
四、调试技巧与工具使用
4.1 DevEco Studio 调试工具
4.1.1 断点调试
在 DevEco Studio 中设置断点进行调试:
- 设置断点:点击代码行号左侧的空白区域
- 启动调试:点击工具栏的 “Debug” 按钮
- 查看状态:在调试面板中查看变量值
updateHealthScore(): void {
// 设置断点,查看 CHECKUP_ITEMS 是否正确加载
debugger // 断点位置
this.totalCheckups = CHECKUP_ITEMS.length
// ...
}
4.1.2 状态监视器
使用 DevEco Studio 的状态监视器实时查看组件状态:
@Entry
@Component
struct HealthApp {
@State healthScore: number = 0
build() {
Column() {
// 状态监视器会显示 healthScore 的实时值
Text(this.healthScore.toString())
}
}
}
4.1.3 日志输出
在关键位置添加日志输出:
updateHealthScore(): void {
console.info('[DEBUG] updateHealthScore called')
console.info('[DEBUG] CHECKUP_ITEMS length:', CHECKUP_ITEMS.length)
this.totalCheckups = CHECKUP_ITEMS.length
console.info('[DEBUG] totalCheckups:', this.totalCheckups)
// ... 更多日志
}
4.2 常见调试场景
场景 1:状态未更新
问题现象:修改了状态但 UI 未刷新
排查步骤:
- 检查是否调用了 update 方法
- 确认状态变量使用了
@State装饰器 - 验证 update 方法中的逻辑是否正确
// 错误示例:忘记调用 update 方法
onCategoryChange(cat: string): void {
this.filterCategory = cat // ❌ 状态已更新,但筛选结果未更新
}
// 正确示例
onCategoryChange(cat: string): void {
this.filterCategory = cat
this.updateFilteredCheckups() // ✅ 更新筛选结果
}
场景 2:初始化顺序错误
问题现象:首次渲染时数据为空
排查步骤:
- 确认
aboutToAppear()中调用了所有必要的 update 方法 - 检查数据初始化是否在组件创建之前完成
// 错误示例:update 方法未在 aboutToAppear 中调用
aboutToAppear(): void {
// ❌ 缺少 updateFilteredCheckups() 调用
}
// 正确示例
aboutToAppear(): void {
this.updateFilteredCheckups() // ✅ 初始化筛选结果
this.updateFilteredTips()
this.updateHealthScore()
}
场景 3:数组引用未改变
问题现象:修改数组内容但 UI 未刷新
排查步骤:
- 确认数组变量使用了
@State装饰器 - 验证是否创建了新数组(而不是修改原数组)
// 错误示例:直接修改数组内容
updateFilteredCheckups(): void {
this.filteredCheckups.length = 0 // ❌ 数组引用未改变
for (let i = 0; i < CHECKUP_ITEMS.length; i++) {
this.filteredCheckups.push(CHECKUP_ITEMS[i]) // ❌ UI 不会刷新
}
}
// 正确示例:创建新数组
updateFilteredCheckups(): void {
let result: CheckupItem[] = [] // ✅ 新数组
for (let i = 0; i < CHECKUP_ITEMS.length; i++) {
result.push(CHECKUP_ITEMS[i])
}
this.filteredCheckups = result // ✅ 赋值新数组触发更新
}
五、性能优化策略
5.1 减少不必要的更新
5.1.1 条件更新
在 update 方法中添加条件判断,避免不必要的更新:
updateFilteredCheckups(): void {
// 检查条件是否真的改变
if (this.filterCategory === this.lastFilterCategory &&
this.showCompleted === this.lastShowCompleted) {
return // 条件未变,跳过更新
}
let result: CheckupItem[] = []
for (let i = 0; i < CHECKUP_ITEMS.length; i++) {
// ... 筛选逻辑
}
this.filteredCheckups = result
// 记录当前条件
this.lastFilterCategory = this.filterCategory
this.lastShowCompleted = this.showCompleted
}
5.1.2 防抖处理
对于频繁触发的操作,使用防抖减少更新次数:
@Entry
@Component
struct SearchApp {
@State searchText: string = ''
@State searchResults: string[] = []
private debounceTimer: number | null = null
onSearchInput(text: string): void {
this.searchText = text
// 清除之前的定时器
if (this.debounceTimer) {
clearTimeout(this.debounceTimer)
}
// 延迟 300ms 后执行搜索
this.debounceTimer = setTimeout(() => {
this.updateSearchResults()
this.debounceTimer = null
}, 300)
}
updateSearchResults(): void {
// 执行搜索逻辑
// ...
}
}
5.2 优化渲染性能
5.2.1 避免重复计算
将计算结果缓存起来,避免重复计算:
@Entry
@Component
struct OptimizedApp {
@State data: number[] = [1, 2, 3, 4, 5]
@State filterThreshold: number = 3
@State filteredData: number[] = []
@State cachedResult: number[] = []
@State cacheValid: boolean = false
updateFilteredData(): void {
// 检查缓存是否有效
if (this.cacheValid) {
this.filteredData = this.cachedResult
return
}
// 执行计算
let result: number[] = []
for (let i = 0; i < this.data.length; i++) {
if (this.data[i] > this.filterThreshold) {
result.push(this.data[i])
}
}
// 更新缓存
this.cachedResult = result
this.cacheValid = true
this.filteredData = result
}
invalidateCache(): void {
this.cacheValid = false
}
}
5.2.2 使用虚拟列表
对于大量数据,使用虚拟列表提升性能:
@Entry
@Component
struct VirtualListApp {
@State items: string[] = Array.from({ length: 10000 }, (_, i) => `Item ${i}`)
build() {
Column() {
// 使用 List 组件实现虚拟滚动
List() {
ForEach(this.items, (item: string) => {
ListItem() {
Text(item)
.fontSize(16)
.padding({ left: 16, right: 16, top: 12, bottom: 12 })
}
}, (item: string) => { return item })
}
.width('100%')
.layoutWeight(1)
.cachedCount(20) // 设置缓存数量
}
.width('100%')
.height('100%')
}
}
六、测试与验证
6.1 单元测试
编写单元测试验证 update 方法的正确性:
// 测试 updateFilteredCheckups 方法
describe('HealthApp', () => {
it('updateFilteredCheckups should filter by category', () => {
const app = new HealthApp()
// 设置初始状态
app.filterCategory = '基础'
app.showCompleted = true
// 执行更新
app.updateFilteredCheckups()
// 验证结果
const result = app.filteredCheckups
expect(result.length).toBeGreaterThan(0)
// 验证所有结果都是基础分类
result.forEach(item => {
expect(item.category).toBe('基础')
})
})
it('updateFilteredCheckups should hide completed items', () => {
const app = new HealthApp()
// 设置状态:隐藏已完成
app.filterCategory = '全部'
app.showCompleted = false
// 执行更新
app.updateFilteredCheckups()
// 验证结果中没有已完成的项目
const result = app.filteredCheckups
result.forEach(item => {
expect(item.done).toBe(false)
})
})
})
6.2 集成测试
测试完整的用户交互流程:
// 测试分类筛选交互
describe('Category Filter Interaction', () => {
it('should update filtered list when category changes', () => {
const app = new HealthApp()
// 初始化
app.aboutToAppear()
// 记录初始数量
const initialCount = app.filteredCheckups.length
// 切换分类
app.onCategoryChange('生化')
// 验证数量变化
expect(app.filteredCheckups.length).not.toBe(initialCount)
// 验证分类正确性
app.filteredCheckups.forEach(item => {
expect(item.category).toBe('生化')
})
})
})
6.3 性能测试
测试 update 方法的性能:
// 性能测试工具
class PerformanceTester {
private startTime: number = 0
start(): void {
this.startTime = Date.now()
}
end(operationName: string): number {
const duration = Date.now() - this.startTime
console.info(`[PERF] ${operationName}: ${duration}ms`)
return duration
}
}
// 测试 updateHealthScore 性能
describe('Performance Tests', () => {
it('updateHealthScore should complete within 10ms', () => {
const app = new HealthApp()
const tester = new PerformanceTester()
tester.start()
app.updateHealthScore()
const duration = tester.end('updateHealthScore')
// 要求在 10ms 内完成
expect(duration).toBeLessThan(10)
})
})
七、最佳实践总结
7.1 状态管理模式
| 模式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| @State + update 方法 | 组件内部状态 | 简单直接,易于理解 | 需要手动调用 update |
| @Prop + @Link | 父子组件通信 | 响应式更新 | 学习曲线较陡 |
| 全局状态管理器 | 跨组件共享状态 | 集中管理,易于维护 | 增加复杂度 |
7.2 调试 checklist
在调试状态相关问题时,检查以下事项:
- 状态变量是否使用了
@State装饰器 - update 方法是否在状态变化后被调用
- 是否在
aboutToAppear()中初始化所有状态 - 数组更新是否创建了新数组(而不是修改原数组)
- 是否有循环依赖或无限更新的情况
7.3 代码审查要点
在代码审查时关注:
- 状态命名:使用清晰的命名,如
filteredCheckups而非checkups - update 方法:确保所有状态变化后都调用了对应的 update 方法
- 错误处理:添加必要的空值检查和边界处理
- 性能优化:避免不必要的重复计算
- 测试覆盖:关键逻辑是否有单元测试覆盖
八、常见错误与解决方案
8.1 错误类型汇总
| 错误信息 | 原因 | 解决方案 |
|---|---|---|
| Cannot read property length of undefined | getter 在 build() 中返回 undefined | 转换为 @State + update 方法 |
| Cannot read property toString of undefined | 数值类型 getter 返回 undefined | 转换为 @State 变量 |
| UI 不刷新 | update 方法未被调用 | 在状态变化后调用 update 方法 |
| 重复渲染 | 状态更新过于频繁 | 使用防抖或条件更新 |
| 内存泄漏 | 事件监听器未清理 | 在 aboutToDisappear 中清理 |
8.2 疑难问题排查
问题:状态更新后 UI 仍不刷新
排查步骤:
- 确认状态变量使用了
@State装饰器 - 检查 update 方法是否被调用
- 验证是否创建了新数组(数组更新需要新引用)
- 使用日志输出确认状态值是否正确更新
问题:应用启动时崩溃
排查步骤:
- 查看错误日志定位问题位置
- 检查
aboutToAppear()中的初始化顺序 - 验证数据是否在组件创建前加载完成
- 添加 try-catch 捕获异常
附录:完整代码示例
A.1 状态管理工具类
/**
* 状态更新管理器
* 提供统一的状态更新和依赖管理
*/
class StateUpdateManager {
private updateQueue: Array<() => void> = []
private isUpdating: boolean = false
enqueue(updateFn: () => void): void {
this.updateQueue.push(updateFn)
this.processQueue()
}
private processQueue(): void {
if (this.isUpdating) return
this.isUpdating = true
while (this.updateQueue.length > 0) {
const updateFn = this.updateQueue.shift()
if (updateFn) {
updateFn()
}
}
this.isUpdating = false
}
}
// 使用示例
const updateManager = new StateUpdateManager()
@Entry
@Component
struct ManagedApp {
@State data: string[] = []
updateData(): void {
updateManager.enqueue(() => {
// 执行状态更新
this.data = ['item1', 'item2', 'item3']
})
}
}
A.2 调试日志工具
/**
* 调试日志工具类
* 提供分级日志输出
*/
class DebugLogger {
private enabled: boolean = true
private prefix: string = '[APP_DEBUG]'
constructor(prefix: string = '[APP_DEBUG]') {
this.prefix = prefix
}
enable(): void {
this.enabled = true
}
disable(): void {
this.enabled = false
}
info(message: string, ...args: any[]): void {
if (this.enabled) {
console.info(`${this.prefix} ${message}`, ...args)
}
}
warn(message: string, ...args: any[]): void {
if (this.enabled) {
console.warn(`${this.prefix} ${message}`, ...args)
}
}
error(message: string, ...args: any[]): void {
if (this.enabled) {
console.error(`${this.prefix} ${message}`, ...args)
}
}
time(label: string): void {
if (this.enabled) {
console.time(`${this.prefix} ${label}`)
}
}
timeEnd(label: string): void {
if (this.enabled) {
console.timeEnd(`${this.prefix} ${label}`)
}
}
}
// 使用示例
const logger = new DebugLogger('[HealthApp]')
logger.info('Initializing app...')
logger.time('updateHealthScore')
updateHealthScore()
logger.timeEnd('updateHealthScore')
参考文献
- HarmonyOS 官方调试指南:https://developer.harmonyos.com/docs
- ArkTS 状态管理文档:https://developer.harmonyos.com/docs
- DevEco Studio 使用手册:https://developer.harmonyos.com/docs
更多推荐



所有评论(0)