鸿蒙应用开发实战【87】— 常见崩溃排查null指针与类型断言

鸿蒙应用开发实战【87】--- 常见崩溃排查null指针与类型断言

本文是「号码助手全栈开发系列」第 87 篇,持续更新中...

开源社区:https://openharmonycrossplatform.csdn.net


前言

ArkTS 严格模式下,空指针和类型断言是运行时崩溃的主要来源。号码助手项目在开发中遇到并解决了多类崩溃问题。本篇整理常见崩溃场景、根因分析和预防措施。

本篇涵盖 :null 指针(!. 与 ?. 选择)、类型断言失败(as 风险)、ResultSet 关闭与游标越界、undefined id 导致的数据库更新失败、Promise 未 catch 异常、页面销毁后更新 State 崩溃。


一、null 指针崩溃

1.1 非空断言 ?. vs 强制解包 !.

typescript 复制代码
// ❌ 危险:如果 card 为 null,直接崩溃
Text(this.card!.phone_number)

// ✅ 安全:使用 ?. 可选链
Text(this.card?.phone_number ?? '')

// ✅ 安全:提前 return
if (!this.card) return
Text(this.card.phone_number)  // 此处可安全使用 !

1.2 项目中实际的 null 指针场景

typescript 复制代码
// CardDetailPage
private async loadData(): Promise<void> {
  try {
    const card = await CardDao.findById(this.cardId)
    if (!card) {
      promptAction.showToast({ message: '卡号不存在或已被删除' })
      this.getUIContext().getRouter().back()  // null 时直接返回
      return
    }
    this.card = card  // 此后可安全使用 this.card!
  } catch (e) { ... }
}

1.3 undefined id 问题

typescript 复制代码
// ❌ 危险:entity.id 可能为 undefined
await CardDao.deleteById(this.card!.id!)  // 双重非空断言

// ✅ 安全:提前校验
if (!this.card || this.card.id === undefined) return
await CardDao.deleteById(this.card.id)

二、类型断言失败

2.1 as 的风险

typescript 复制代码
// 数据库中可能存储了非法值
status: rs.getString(rs.getColumnIndex('status')) as BindingStatus

// 如果数据库返回 '未知状态',as 不会阻止崩溃
// 方案:parseRow 中加兜底
const rawStatus = rs.getString(rs.getColumnIndex('status'))
status: ['使用中', '待换绑', '待注销', '已停用'].includes(rawStatus)
  ? rawStatus as BindingStatus
  : '使用中'

三、ResultSet 操作规范

typescript 复制代码
// ❌ 危险:未检查行数直接读取
const rs = await store.query(predicates, COLS)
const id = rs.getLong(rs.getColumnIndex('id'))  // 游标在-1位置

// ✅ 正确:先 goToFirstRow 再读取
rs.goToFirstRow()
const id = rs.getLong(rs.getColumnIndex('id'))

// ✅ 或者检查 rowCount
if (rs.rowCount > 0 && rs.goToFirstRow()) {
  // 安全读取
}
rs.close()  // 务必关闭

四、页面销毁后更新 State

typescript 复制代码
// 场景:异步回调在页面已销毁后尝试更新 State
private async doBackup(): Promise<void> {
  this.backing = true
  try {
    // 异步操作
  } finally {
    // 如果页面已被销毁(用户按了返回),此处崩溃
    this.backing = false  // 崩溃:Cannot update state after page destroyed
  }
}

预防 :在页面生命周期 onPageHide 或 aboutToDisappear 中取消待处理的异步操作。


小结

崩溃类型 原因 预防 检测方式
null 指针 对象为 null 时用 ! 解包 提前校验 + ?. + ?? 兜底 编译时 lint
类型断言 as 转换不兼容类型 parseRow 加兜底默认值 单元测试
ResultSet 未 goToFirstRow 直接读取 先检查 rowCount 再读取 Code Review
undefined id 实体可选 id if (id === undefined) return 静态分析
异步 State 页面销毁后更新 取消待处理异步操作 运行时监控

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

相关推荐
xq952719 小时前
ArkTS Component Generator 插件横空出世
harmonyos
Fate_I_C19 小时前
Capacitor 插件鸿蒙化实战:@capacitor/device 从安装到模拟器验证全记录
华为·harmonyos
2501_919749031 天前
华为鸿蒙免费记账与生活统计APP—小羊统计
华为·生活·harmonyos·鸿蒙
Fate_I_C1 天前
Capacitor 应用鸿蒙化实战:用 hionic 把 React 应用跑在 OpenHarmony 上
react.js·华为·harmonyos
SuperHeroWu71 天前
华为云码道接入 DevEco CLI 鸿蒙应用开发AICoding
华为·华为云·harmonyos
ChinaDragonDreamer1 天前
HarmonyOS:User Authentication Kit简介
华为·harmonyos
m0_738185821 天前
Flutter 鸿蒙化实战:qrcode_flutter 适配 OpenHarmony,二维码生成与识别
数码相机·flutter·华为·harmonyos·鸿蒙
万物智能信息科技1 天前
血氧心跳传感器MAX30100芯片驱动开发—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
人工智能·驱动开发·华为·开源·harmonyos·鸿蒙
老陈说编程1 天前
1. 鸿蒙 (HarmonyOS) 2012 至 2026 年的发展历程
分布式·华为·个人开发·harmonyos·鸿蒙·鸿蒙系统·程序员创富