HarmonyOS应用实战-启示散页-70-StorageLink 回归别只测页面:覆盖水合顺序、空值与重进路径
HarmonyOS 应用实战 70StorageLink 回归别只测页面覆盖水合顺序、空值与重进路径StorageLink 的问题经常不是“页面打不开”而是时序问题首次挂载拿到默认值切换题库后某个 Builder 对未水合对象调用toString删除题库后旧 id 又被重进页面读取。只点一遍页面测不到这些边界。本文解决四个问题把 StorageLink 回归拆成水合、空值、重进三类避免 Builder 里直接使用未守卫对象新增 key 时补齐启动、重置和删除链路用脚本检查危险访问模式StorageLink 不是持久化本身它只是 AppStorage 和页面状态的绑定。真正持久化仍在 Preferences。回归时必须同时看启动水合、页面绑定和持久化写入。故障链新增 StorageLink key - 启动未 setOrCreate - 页面 Builder 读取 undefined - 调用 toString 崩溃StorageLink是页面和AppStorage的绑定不是持久化协议。把它当最终事实就会在首次挂载、清空数据和重进时踩空值。新增 key 要有生命周期清单每个 StorageLink key 都要说明默认值、启动水合、写入 owner、重置路径和删除路径。interfaceStorageLinkKeySpecT{key:string;defaultValue:T;hydrateOwner:string;writeOwner:string;resetIncluded:boolean;}新增 key 要有完整生命周期。定义、默认值、水合、消费、重置、删除缺一项回归时就可能只在某条路径崩。启动时先 setOrCreate再挂页面新增 key 后如果只在页面里声明 StorageLink首次进入就可能拿到 undefined。classAppStorageHydrator{hydrate():void{AppStorage.setOrCreate(currentDeckId,DEFAULT_DECK_ID);AppStorage.setOrCreate(deck.changedAt,0);AppStorage.setOrCreate(favorite.changedAt,0);AppStorage.setOrCreate(questionHistory.changedAt,0);}}页面挂载前先setOrCreate能保证StorageLink至少拿到安全默认值。持久化恢复再覆盖默认值顺序不能反过来。Builder 里不要直接调用可空对象方法ArkUI Builder 中应先通过方法取安全默认值避免undefined.toString()或数组.length崩溃。Componentstruct FavoriteBadge{StorageLink(favorite.count)privatefavoriteCount:number|undefined0;privatesafeFavoriteCount():number{returnthis.favoriteCount??0;}build(){Text(${this.safeFavoriteCount()});}}Builder里不要直接调用可空对象方法。数组、对象和字符串都先经过安全方法转换再进入 UI 表达式。重置和删除要同步 key 生命周期清空历史、删除题库、退出演示模式时如果只清 Preferences 不更新 AppStorage页面会显示旧值。classAppStateResetService{asyncclearQuestionHistory():Promisevoid{awaitQuestionHistoryRepository.saveAll([]);AppStorage.setOrCreate(questionHistory.changedAt,Date.now());AppStorage.setOrCreate(questionHistory.count,0);}}重置和删除要同步 key 生命周期否则页面状态清掉了AppStorage还留着旧引用或者持久化清了页面仍显示旧值。回归脚本先抓危险模式脚本不能替代真机但能快速发现 Builder 中直接访问可空值的写法。rg-nStorageLink|\.toString\(|\.length|\$\{.*StorageD:\ProgramData\huawei\lesson\The_Book_of_Answers\entry\src\main\ets D:\ProgramData\huawei\lesson\The_Book_of_Answers\libraryHSP\src\main\ets危险模式扫描适合放在回归前。它不能证明运行无 bug但能快速找出.length、模板字符串和未守卫对象这类高危写法。StorageLink 回归矩阵回归要覆盖首次启动、切换题库、清空历史、删除当前题库、重进页面。路径检查点首次启动key 已 setOrCreate切换题库changedAt 通知相关页清空历史count 和列表都归零删除当前题库currentDeckId 回退重进页面不读取旧 undefined回归矩阵要覆盖水合顺序、空值、重进和删除路径。只点当前页面一次测不到StorageLink最容易出问题的时序边界。给每个 StorageLink key 建生命周期表StorageLink出问题时往往不是单个页面错而是 key 的生命周期缺一段。新增 key 时就应该写表谁定义、默认值是什么、何时水合、哪些页面消费、重置和删除时怎么处理。key默认值水合 owner消费页面重置/删除home.searchHistory[]Persist.hydrate()首页、搜索面板清历史时同步清空currentDeckId默认题库 id启动状态水合首页、选择器、抽取页删除题库时回退favorite.changedAt0收藏服务写入收藏页、首页卡片清收藏时更新生命周期表比单次页面测试更有价值因为它能直接发现“定义了但没水合”“清了持久化但没清 AppStorage”这类问题。Builder 消费前先变成安全值ArkUI Builder 里最容易出现的危险写法是直接对StorageLink数组或对象做.length、模板字符串或.toString()。建议先用普通方法返回安全默认值再进入 UI 表达式。privategetSafeHistoryCount():number{returnArray.isArray(this.searchHistory)?this.searchHistory.length:0;}privategetCurrentDeckLabel():string{returnthis.currentDeckNamethis.currentDeckName.length0?this.currentDeckName:默认题库;}这里用普通方法而不是 Builder 里的临时语句是为了让空值处理集中、可搜索、可单独复查。回归矩阵要覆盖水合、空值、重进和清理StorageLink回归不能只看当前页面是否显示。更有效的矩阵是首次安装、普通冷启动、清空 Preferences、删除当前题库、切换 Tab 后返回、重置应用数据。每条路径都看页面是否读取安全值。路径要观察失败时先查首次安装key 已有默认值AppStorage.setOrCreate是否早于页面清空数据页面不崩溃Builder 是否直接取空对象删除题库currentDeckId 回退删除流程是否同步 keyTab 重进展示最终事实页面是否只改局部状态没有真机或模拟器运行记录时文章只能写静态回归清单和危险模式扫描不能声称运行崩溃已完全覆盖。危险模式扫描要配合人工判断扫描.length、模板字符串和.toString()不是为了禁止所有用法而是为了找出StorageLink值未经守卫就进入 Builder 的位置。命中后要看变量来源普通局部数组可以继续用StorageLink 数组就要改成安全方法。rg-nStorageLink|\.length|\.toString\(|\$\{entry hsp har检查时建议把结果分成三类安全局部变量、已守卫的 StorageLink、未守卫的 StorageLink。只有第三类是必须修的风险。这样文章不会变成“禁止使用 length”的误导而是教读者识别真正的状态时序问题。人工评审时把每个 key 走一遍删除路径StorageLink的删除路径经常被漏测。评审时不要只看启动水合还要看清空历史、删除题库、清空收藏、重置应用数据时对应 key 是否同步更新。删除路径检查 home.searchHistory - 清空历史后 AppStorage 为 [] currentDeckId - 删除当前题库后回退到可用 id favorite.changedAt - 清空收藏后刷新信号更新 diagnostics.changedAt - 清空诊断账本后页面重新读取这一步能发现“页面看起来清了但 AppStorage 里仍有旧值”的问题。第 70 篇的重点不是记住某个装饰器而是把 key 的生老病死都收进一张可复查清单。小结StorageLink 回归不能只看页面能否打开。新增 key 要补齐启动水合、默认值、写入 owner、重置路径和删除路径Builder 只使用安全方法读取值才能覆盖首次挂载、空值和重进路径。

相关新闻