发布时间:2026/7/21 3:24:33
HarmonyOS应用实战-启示散页-06-仪式感动画不要卡业务:用 DrawingPage 隔离抽取和转场 HarmonyOS应用实战-启示散页-06-仪式感动画不要卡业务用 DrawingPage 隔离抽取和转场答案之书需要一点仪式感提问、翻动、停顿、出现答案。但动画一旦和业务抽取绑在一起就很容易出问题。动画还没结束结果已经写历史用户返回了定时器还在跑抽取失败了页面仍播放到最终态。更稳的做法是把 DrawingPage 当成状态机把业务结果和转场节奏隔开。这篇文章会把问题拆成四个可落地的点用 DrawingPage 承接抽取流程不让首页直接处理动画。业务先拿结果动画按状态展示不反向决定数据。处理定时器清理、返回中断和失败态。让历史、收藏和页面显示都基于同一个抽取结果。1. 动画不能反过来驱动业务很多页面会写成“动画结束后再随机抽答案”。这会让业务结果依赖 UI 时间动画取消、页面返回、定时器丢失都会影响抽取。答案之书更稳的路径是先由 Service 得到结果再让 DrawingPage 根据结果播放揭示动画。privateasyncbegin():Promisevoid{this.phasedrawing;try{constresult:DrawAnswerResultawaitAnswerDrawService.draw({deckId:this.deckId,question:this.question});this.resultresult;this.phaserevealing;this.startRevealTimer();}catch(err){this.phasefailed;}}业务完成后才进入 revealing。动画可以慢一点但不能决定答案是否存在。2. 页面状态机要少而清楚DrawingPage 至少有 idle、drawing、revealing、done、failed 五种状态。不要用多个 boolean 拼状态例如loading showCard hasError后期很难判断组合是否合法。typeDrawingPhaseidle|drawing|revealing|done|failed;Stateprivatephase:DrawingPhaseidle;Stateprivateresult:DrawAnswerResult|nullnull;StateprivaterevealProgress:number0;单一 phase 能让 UI 分支和调试日志都更直接。出现异常时先看 phase 停在哪一步。3. 首页只传输入不参与抽取细节首页收集问题和当前题库 id然后跳转到 DrawingPage。它不应该提前随机也不应该写历史。这样首页可以保持轻抽取页成为完整流程的唯一拥有者。this.pathStack.pushPath({name:RouteName.Drawing,param:{deckId:this.currentDeckId,question:this.question.trim()}asDrawingParam});首页传的是上下文不是结果。DrawingPage 才负责拿结果、展示结果和交给历史服务。4. 参数进入页面先做兜底导航参数可能为空特别是调试、深链或后续扩展入口。DrawingPage 在aboutToAppear中解析参数缺失时给出错误态不要让空 deckId 进入 Service 后再出现难懂错误。interfaceDrawingParam{deckId:string;question?:string;}privatereadParam():DrawingParam|null{constparamthis.pathStack.getParamByName(RouteName.Drawing)asDrawingParam|undefined;if(!param?.deckId){returnnull;}returnparam;}参数校验是页面入口边界。Service 仍会校验但页面可以更早给用户可理解的反馈。5. 定时器必须跟页面生命周期绑定动画通常需要setTimeout或setInterval。如果页面返回后不清理定时器回调还会修改已离开的页面状态轻则日志异常重则状态错乱。答案之书需要在离开页面时清理所有动画句柄。privaterevealTimer:number-1;aboutToDisappear():void{if(this.revealTimer!-1){clearInterval(this.revealTimer);this.revealTimer-1;}}动画资源属于页面生命周期。页面消失后不再允许它继续推进状态。6. 历史写入放在结果确认点历史记录应该写在抽取结果生成后而不是动画彻底结束后。用户中途返回也代表这次抽取发生过如果产品希望只记录看完的答案那也要显式定义。答案之书更适合在拿到结果后记录历史。constresult:DrawAnswerResultawaitAnswerDrawService.draw(options);awaitHistoryService.appendFromDraw(result);this.resultresult;this.phaserevealing;历史的来源是领域结果不是动画帧。这样历史列表和收藏按钮都能使用同一个 result。7. 失败态要停住动画抽取失败时继续播放动画会让用户等到最后才看到空白。DrawingPage 应该在 Service 抛错后直接进入 failed并提供重试或返回。错误提示也应该区分“题库不存在”和“题库没有答案”。BuilderFailedPanel(){Column({space:12}){Text(this.errorMessage||暂时无法抽取答案)Button(返回题库选择).onClick(()this.pathStack.pop())}}失败态是流程的一部分不是兜底文案。只要业务可能失败UI 就要给出明确出口。8. 动画参数不要散落在 UI 里转场时长、进度步长、结果停顿时间最好集中成常量。这样后续调节仪式感时不会误改抽取逻辑。动画常量也能让真机调优更有依据。constREVEAL_TOTAL_MS:number1200;constREVEAL_TICK_MS:number40;privatestartRevealTimer():void{conststartedAt:numberDate.now();this.revealTimersetInterval((){this.revealProgressMath.min(1,(Date.now()-startedAt)/REVEAL_TOTAL_MS);if(this.revealProgress1){this.phasedone;clearInterval(this.revealTimer);}},REVEAL_TICK_MS);}动画参数集中后业务代码不需要因为“想慢一点”而被改动。9. 验证与排障DrawingPage 的验证要覆盖时间和中断快速返回、连续进入、抽取失败、动画未结束时收藏、切换题库后再抽。尤其要看定时器是否清理历史是否只写一次。验证点 1. 首页只负责 push DrawingPage 2. DrawingPage 进入后先拿 DrawAnswerResult 3. 返回页面后没有定时器继续打印日志 4. 抽取失败时 phasefailed不播放到 done 5. 历史记录不因动画重复触发而写两次如果页面偶发卡在 loading优先看 phase 切换和 Service 异常处理而不是只调动画时长。还有一个需要在评审时说清楚的边界返回不是业务失败。只要 Service 已经给出结果并写入历史用户中途离开只代表不再观看本次动画。相反如果 Service 还没有返回结果就离开页面页面要清理定时器和挂起状态不能在后台继续推进 UI。把这个边界写进状态机后续调动画节奏时就不会误伤数据链路。如果产品后来增加“再抽一次”也应该从 done 状态重新进入 drawing而不是复用上一轮 result 改文案。每一次抽取都有独立结果、独立历史写入和独立动画周期这样连续操作才不会把两次答案混在同一个页面状态里。验证清单清应用数据后从冷启动进入确认默认数据、页面状态和日志分支符合预期。对本文涉及的写路径准备正常、空值、重复、越界四类输入确认错误停在 Service 或 Repository。页面返回、重新进入、切换题库、收藏、历史或删除后确认对应刷新信号触发重新读取。修改资源或模块归属后重新构建确认 HAP、HAR、HSP 的依赖方向没有反转。涉及真机体验、备份恢复、发布素材的内容单独记录是否已经在设备或平台侧验证。常见问题与处理现象先看哪里处理方式返回后仍有动画日志aboutToDisappear 是否清理 timer记录并清理所有句柄抽取失败仍显示翻牌失败分支是否进入 failedService 抛错后停止动画历史重复写入是否在多个动画回调里 append只在拿到 DrawAnswerResult 后写一次首页越来越复杂首页是否承担抽取和动画首页只传 DrawingParam小结仪式感应该增强体验不能接管业务。DrawingPage 用状态机隔离抽取结果和动画节奏既能保留氛围也能让数据链路可控。

相关新闻

2026/7/21 3:24:33

专科生论文写作利器:10款AI工具实战指南

1. 专科生学术写作痛点与AI工具崛起(开头段自然引入主题,前100字含核心关键词) 最近在指导几位专科同学修改论文时,发现他们普遍面临三大难题:文献检索效率低、论文框架搭建困难、语言表达不够学术化。恰好这半年我系统…

2026/7/21 3:19:33

如何快速恢复丢失的Ren‘Py游戏源码:终极反编译工具指南

如何快速恢复丢失的RenPy游戏源码:终极反编译工具指南 【免费下载链接】unrpyc A renpy script decompiler 项目地址: https://gitcode.com/gh_mirrors/un/unrpyc 你是否曾经遇到过RenPy游戏项目源码丢失的尴尬情况?或者需要分析已编译的游戏脚本…

2026/7/21 21:01:51

国产大模型选型实战:从SOTA榜单到业务落地的关键步骤

1. 先搞清楚“SOTA每周易主”到底意味着什么如果你最近关注国内AI动态,大概率会刷到“某模型又刷新SOTA”这类消息。SOTA(State Of The Art)原本指某项任务上当前最优的技术水平,但现在这个词在国产大模型领域几乎成了周更话题——…

2026/7/21 21:01:51

VC++运行库缺失的5种解决方案:从游戏开发到分发的完整指南

1. 项目概述:为什么VC运行库是游戏开发的“隐形守护者”如果你是一名游戏开发者,或者哪怕只是偶尔自己捣鼓一些独立游戏项目,那么“应用程序无法启动,因为找不到VCRUNTIME140_1.dll”或者“MSVCP140.dll丢失”这类弹窗&#xff0c…

2026/7/21 21:01:51

大模型评估体系:从标准统一到国家层面独立评测的技术实践

最近在AI圈里有个话题越来越热:当我们谈论大模型能力时,到底在谈论什么?是跑分榜单上的数字,还是实际业务场景中的表现?这个问题背后,其实隐藏着一个更深刻的挑战——如何建立真正独立、可信的模型评估体系…

2026/7/21 20:56:50

Tolaria代码重构引擎:本地部署、API集成与批量代码质量分析实践

这次我们来看一个名为Tolaria的项目,它来自RefactoringHQ。如果你正在寻找一个能帮你快速、批量地重构和优化代码的工具,并且希望它能本地运行、支持自定义规则、提供清晰的API,那么这个项目值得你花几分钟了解一下。Tolaria 的核心定位是一个…

2026/7/20 6:33:00

Unity与Python本地通信:基于Flask的跨语言数据交换实战

1. 项目概述:为什么我们需要一个本地通信服务器?在游戏开发、数字孪生、仿真训练等众多领域,Unity作为强大的实时3D内容创作平台,其核心逻辑通常由C#驱动。然而,当我们需要进行复杂的数据分析、机器学习推理、科学计算…

2026/7/21 0:08:52

华为OD机试 新系统真题 【酒店服务记录分析】

酒店服务记录分析(C++/Go/C/Js/Java/Py)题解 华为OD机试 新系统真题 华为OD上机考试 新系统真题 7月19号 100分题型 华为OD机试新系统真题目录点击查看: 华为OD机试新系统真题题库目录|机考题库 + 算法考点详解 题目内容 你是某连锁酒店的数据分析师,酒店每天都会用一串编…

2026/7/21 0:08:52

华为OD机试 新系统真题 【小明的顺风车】

小明的顺风车(C++/Go/C/Js/JAVA/Py)题解 华为OD机试新系统真题 华为OD上机考试新系统真题 7月19号 200分题型 华为OD机试新系统真题目录点击查看: 华为OD机试新系统真题题库目录|机考题库 + 算法考点详解 题目内容 小明自驾回家,为节省旅途成本,决定在网上挂出顺风车服务…

2026/7/21 20:02:44

3个高效策略:快速掌握Axure中文界面配置

3个高效策略:快速掌握Axure中文界面配置 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英文界面感…