鸿蒙应用开发实战【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 页面销毁后更新 取消待处理异步操作 运行时监控

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


相关资源:

相关推荐
Magic-ZYJ2 小时前
HarmonyOS Release 构建安全:ArkGuard 混淆、签名配置与秘密管理
安全·华为·harmonyos·移动应用开发·心晴手记
见山是山-见水是水4 小时前
拆解HarmonyOS网络请求适配:原生鸿蒙页面的实现路径与调试方法
华为·harmonyos
m0_749690234 小时前
【寻迹校园 HarmonyOS NEXT 实战 36】深色模式不是反色:用语义 Token 管理品牌色与状态色
harmonyos·arkts·深色模式·ui设计·主题设计
lqj_本人5 小时前
鸿蒙跨端实战_QT后台切换导致OpenGLES上下文丢失:黑屏自救指南
qt·华为·harmonyos
OH_TPC6 小时前
HarmonyOS APP开发---“数据眼“健康追踪App,需要用到这个库
华为·harmonyos·鸿蒙
lilian2337 小时前
Harmony os 技术实战|拼豆制图49:五组分类视觉规则如何收口成一张配置表
华为·harmonyos
2501_919749038 小时前
华为鸿蒙免费决策APP—小羊挠头
华为·harmonyos·鸿蒙
m0_749690238 小时前
【寻迹校园 HarmonyOS NEXT 实战 37】一套 ArkUI 适配四档宽度:sm、md、lg、xl 响应式 Shell 实战
华为·harmonyos·arkui·navigation·响应式布局·多设备适配
RisunJan10 小时前
HarmonyOS 架构精读:从系统分层到应用模型
华为·架构·harmonyos
见山是山-见水是水10 小时前
从需求到页面:鸿蒙原生 Ability 与 ArkTS 交互的 ArkTS 原生实现
华为·harmonyos