ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

HarmonyOS 7 + Form Kit + UIAbility 实战:运营看板卡片的刷新策略、状态同步与点击回流【鸿蒙心迹】

HarmonyOS 7 + Form Kit + UIAbility 实战:运营看板卡片的刷新策略、状态同步与点击回流【鸿蒙心迹】 这一篇我想聊的是看起来很轻、做起来却很容易失衡的一类功能桌面卡片。很多人第一次做运营看板卡片最先关注的是“怎么把一块卡片显示出来”。但真正把它做成一个能用、可信、可跳转、可同步的业务入口以后你会发现难点根本不在“显示”而在“卡片和应用主页面之间到底能不能长期保持一致”。一、卡片最容易出现的问题不是不好看而是“不可信”我这次做的是一个运营看板卡片目标很明确在桌面或负一屏快速看到核心业务数据支持手动刷新点击卡片能直接进入应用详情页卡片上的数据和应用内的数据要尽量一致。最早做 Demo 的时候我觉得事情很简单从仓储里拿一份数据绑定到卡片点一下刷新就重新取一份点卡片就跳详情页。但一旦真正开始联调很快就发现问题一点都不少卡片上明明是旧数据应用里却已经更新了用户手动刷新以后只改了数值没有改刷新时间卡片点进去能打开页面但页面不知道这次来自卡片卡片多实例存在时哪个实例更新了根本说不清用户以为看到的是“实时数据”其实是上一次缓存结果。说白了卡片功能最怕的不是样式一般而是用户不再相信它展示的内容。二、我后来先把问题拆成三条链刷新、同步、回流卡片一旦上业务就不能只当成一个 UI 组件来看。我最后是按三条链来梳理它的刷新链卡片什么时候拉数据谁来触发刷新同步链数据、刷新时间、状态文案怎么一起更新回流链点击卡片以后应用如何识别来源并落到正确页面。这三个词看起来抽象但特别适合治理这类功能。因为卡片的难点刚好就集中在这三件事上。如果这三条链没理顺表面上你已经“做出一张卡片”了实际上只是做出了一张可能会过期、可能会跳错、也可能会误导用户的卡片。三、刷新不是越频繁越好关键是触发点得对刚开始做卡片时很多人会本能地往“高频刷新”上走。可做一阵子就会发现高频刷新并不等于高质量刷新。它可能带来两个问题数据源压力变大刷新动作频繁但展示结果未必稳定。所以我后来把刷新触发点分成了三类首次添加卡片初始化就拉一次定时刷新例如每 15 分钟刷新一次用户主动刷新用户点击刷新按钮时立即同步。也就是说刷新策略不是“拼命更新”而是要能解释清楚这次更新是为什么发生的。在 FormAbility 这一层我最后把这几个触发点都收到了同一条数据更新方法里privateasyncupdateFormData(formId:string){constdata:DashboardDataawaitthis.repository.getDashboardData()constformDataformBindingData.createFormBindingData({orderCount:data.orderCount,activeUser:data.activeUser,amount:data.amount,refreshTime:data.refreshTime})awaitformInfo.updateForm(formId,formData)console.info(updateFormData success, formId:${formId})}我很喜欢这种收法因为它带来一个非常直接的好处首次加载走它定时刷新走它手动刷新也走它。也就是说卡片的数据出口只有一个。这比每个触发点都自己拼一份卡片数据要稳定得多。四、真正容易乱掉的是“数据同步”而不是“数据刷新”一开始我也以为只要刷新成功卡片就对了。后来发现不是这样。比如卡片上有三个数字今日新增活跃用户成交金额。如果这三个数字更新了但“刷新时间”还是旧的用户就会怀疑。反过来如果刷新时间变了但数值没变也会让人觉得卡片不靠谱。所以“同步”这件事真正要同步的不是某一个字段而是一组互相能解释的状态核心数据刷新时间同步状态数据来源最近一次同步结果。页面上我后面也专门给了一个可观察区域把这些同步信息单独展示出来而不是只给一个“同步成功”的结论。这张图里红色标注圈出来的内容我觉得特别适合拿来解释“同步链”实例ID解决的是“到底是哪一张卡片”刷新时间解决的是“这次数据什么时候来的”同步结果解决的是“卡片有没有真正更新成功”回流目标页则把同步和点击行为接到了同一条业务链上。很多文章只讲卡片绑定数据但如果不把这些同步证据展示出来读者其实还是很难知道卡片为什么会“可信”。五、点击回流最怕的是“能跳但跳不明白”卡片点进去打开页面这件事看起来很基础但真正做起来最容易留下“半截工程”。什么叫半截工程就是用户点了卡片页面确实打开了可应用并不知道这次打开来自卡片来自哪一张卡片用户点的是哪个区域该进入首页、详情页还是某个子 Tab。如果不把这些信息带进去卡片就只是一个“能打开 App 的快捷方式”而不是一个真正的业务入口。所以我在点击回流这块做了两件事卡片事件统一走onFormEvent回流时显式携带fromcard、pageIndex这类参数。下面这段代码就是整个回流链的核心onFormEvent(formId:string,message:string){if(messagecard_click){letwantnewWant()want.bundleNamecom.example.dashboardwant.abilityNameMainAbilitywant.parameters{page:Index,from:card,formId:formId}this.context.startAbility(want)}}这个写法最值钱的地方不在“能打开页面”而在“打开之后页面有上下文”。有了fromcard以后首页完全可以决定是否显示卡片来源提示是否直接滚到某个数据模块是否记录一次卡片回流事件是否在详情页回写停留统计。这时卡片才真正从“展示模块”变成了“业务入口”。六、应用页为什么要保留卡片预览和回流痕迹做这类功能时我现在特别不建议把卡片和应用页完全割裂开。因为如果页面里一点卡片痕迹都没有开发和测试很难验证两件事卡片当前显示的内容到底和应用内是不是一致用户从卡片过来以后这次回流是否真的生效。所以我后面在应用页里有意保留了三块信息当前卡片预览最新刷新时间卡片点击回流后的目标页说明。这张手机图其实特别像真实项目调试时的“中间态页面”上半部分让你能看到卡片当前展示什么“刷新入口”告诉你这次刷新由谁触发“状态同步”让你知道当前界面看到的是不是最新状态“卡片点击”则把桌面卡片和应用详情页的关系讲清楚了。而且红色箭头、红圈这种讲解方式非常适合正文配图。它不会把画面做得很花但能很快帮读者抓住重点。七、为什么这次工程最后能稳定我觉得关键是“实例可追踪”很多桌面卡片示例在 Demo 层其实已经足够了但真上业务以后经常会少一个东西实例追踪能力。一旦用户在桌面放了多张卡片或者卡片重新创建、重新绑定问题就会变得非常现实这次刷新的是哪一张卡片某张卡片没更新是数据问题还是实例问题某次点击回流到底来自桌面还是应用内按钮。所以我后面几乎把所有关键节点都带上了formId包括初始化添加定时刷新手动刷新点击回流同步日志。这样一来只要看到日志就能很快知道哪条链路出了问题。八、从开发视角看这个项目真正成型是在“结构收拢”之后如果从 DevEco 的工程视角回头看这次实战我觉得最值得记下来的不是卡片做得多漂亮而是结构终于收拢了。这张图里其实已经把整个结构讲得很清楚了左边工程目录把form、model、pages分开了中间代码把“卡片数据源”“定时刷新”“点击回流”都收在同一个 FormAbility 里右侧模拟器同时展示了桌面卡片和应用详情页底部日志则把“定时刷新事件”“数据同步日志”“点击回流日志”都串起来了。也就是说这个功能最后之所以稳不是因为某一个 API 很强而是因为触发点被统一了数据出口被统一了回流入口也被统一了。这三件事一旦收拢卡片功能就不再是零碎补丁而是一个有工程闭环的小系统。九、本文小记如果让我用一句话总结这次实战我会写成桌面卡片真正难的不是“显示”而是“长期一致”。一致的是什么数据一致时间一致状态一致点击后的目标路径也一致。对我自己来说这次做完以后有几个判断基本已经定下来了卡片刷新一定要有清晰触发点数据同步不能只改数字还要同步时间和状态点击回流一定要带来源和目标页参数多实例卡片一定要可追踪页面里最好保留一部分卡片联动痕迹方便验证和排查。如果你现在也在做 HarmonyOS 的卡片类能力我的建议是先别急着优化样式先把刷新链、同步链、回流链这三条线走通。这三条线一旦顺了卡片才真正配得上“业务入口”这四个字。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进