鸿蒙应用开发实战【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
  }
}

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


小结

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

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


相关资源:

相关推荐
条tiao条5 小时前
MVVM架构与ArkUI状态管理
华为·架构·harmonyos·鸿蒙·mvvm
程序员黑豆7 小时前
鸿蒙应用开发:一次开发多端适配与自适应布局实战
前端·harmonyos
三翼鸟数字化技术团队8 小时前
GN (generate ninja) 学习手册
harmonyos
程序员黑豆9 小时前
鸿蒙应用开发:网络请求三种方式详解(http / rcp / axios)
前端·harmonyos
小雨青年9 小时前
【HarmonyOS 7 沉浸光感深度实战】 02 全局开关、MaterialState 与最小 Demo
华为·harmonyos
lilian23310 小时前
Harmony os 技术实战|拼豆制图06:收藏 ID、生成记录与重启恢复怎么不打架
android·java·数据库·harmonyos
程序员黑豆10 小时前
鸿蒙应用开发之生命周期方法完全指南
前端·harmonyos
萌新源12 小时前
电赛C题:我用星闪+UWB做了一个数字钥匙门锁系统,开源了
c语言·华为·开源
HMS Core12 小时前
借助AR Engine人脸识别与跟踪能力,直播不露脸也生动
ar·harmonyos