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

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


相关资源:

相关推荐
贾伟康2 小时前
【HarmonyOS 7新能力|028】Core Vision Kit工程封装:把接入逻辑放进可维护的分层结构
计算机视觉·harmonyos·arkts·端侧ai·harmonyos 7
马剑威(威哥爱编程)4 小时前
【共创稿事节】HarmonyOS 7 互动卡片实战:摇一摇触发静态转动态,前景元素出框
华为·harmonyos
贾伟康4 小时前
【HarmonyOS 7新能力|029】3DGS工程封装:把接入逻辑放进可维护的分层结构
harmonyos·arkts·三维重建·3dgs·harmonyos 7
马剑威(威哥爱编程)4 小时前
【共创稿事节】HarmonyOS 7 闪控窗实战:标准悬浮窗、侧边栏暂存与闪控球一键切换
华为·harmonyos
贾伟康5 小时前
【HarmonyOS 7新能力|019】平行视界入门实战:从能力边界到最小可运行链路
harmonyos·arkts·arkui·harmonyos 7·平行视界
技术任我行XTing6 小时前
【DFX系列】Flutter 鸿蒙应用外接纹理介绍及问题定位
flutter·harmonyos
三翼鸟数字化技术团队6 小时前
WiFi-DensePose × OpenHarmony 智慧家居融合
harmonyos
HarmonyOS_SDK6 小时前
AI 赋能 Push Kit 场景化消息开发,高效完成鸿蒙应用推送能力接入
harmonyos
大雷神7 小时前
【共创稿事节】HarmonyOS ArkGraphics 3D实操——做一个可暂停、可拖动的音箱场景动画
harmonyos
anthonyzhu7 小时前
MacOS27 x86限制引发的pod的问题处理
华为·harmonyos