尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

HarmonyOS 7.0 / API 26 互动卡片刷新实战:后台数据、点击跳转和过期状态如何避免打架

HarmonyOS 7.0 / API 26 互动卡片刷新实战:后台数据、点击跳转和过期状态如何避免打架 HarmonyOS 7.0 / API 26 互动卡片刷新实战后台数据、点击跳转和过期状态如何避免打架先把问题摆出来互动卡片不是把页面缩小放到桌面。它的麻烦在于数据轻、入口快、状态容易过期。后台刷新刚回来用户又点进详情如果没有版本控制就会出现卡片显示和详情页不一致。这篇只盯一个能力点互动卡片。我不把它写成概念说明而是按排查路径写问题怎么出现怎么复现代码怎么落地边界怎么验最后怎么封装成以后能复用的写法。版本边界和适用场景项目本文口径系统范围HarmonyOS 7.0 / API 26 及以上能力适配适合页面桌面卡片、快捷服务入口、提醒卡片、轻量数据面板常见风险卡片数据过期、点击跳转参数错、后台刷新覆盖用户意图、异常时显示空白验收目标数据有版本号、点击有意图快照、过期状态有兜底、跳转参数可校验这里要先定边界。很多页面问题不是 ArkUI 写错了而是版本能力、设备形态、生命周期、异步任务混在一起后状态没有被分层。只要边界不清楚代码就会越补越乱。常见错误把能力适配写成一个布尔开关刚开始最容易写成下面这样。能跑但后面会很难维护。interface FeatureSwitch { enabled: boolean; deviceType: string; scene: string; } class BadFeatureAdapter { buildState(input: FeatureSwitch): string { if (!input.enabled) { return fallback; } if (input.deviceType phone) { return phone-mode; } if (input.deviceType tablet) { return tablet-mode; } return default-mode; } }问题在于它只关心“开没开”没有记录为什么进入这个分支。等页面出现抖动、丢状态、审核截图异常或者多设备表现不一致时只能靠猜。改法把输入、策略和结果拆开我更倾向于把适配拆成三层输入层只收集事实策略层做判断结果层给 UI 或任务调度使用。这样改完以后日志能看懂单测也能写。type DeviceShape phone | foldable | tablet | pc; type FeatureScene preview | editing | handoff | review; interface FeatureContext { apiVersion: number; deviceShape: DeviceShape; scene: FeatureScene; widthVp: number; heightVp: number; lowPowerMode: boolean; } interface FeatureDecision { mode: full | compact | safe | off; reason: string; shouldRecordMetric: boolean; } export class FeaturePolicy { decide(ctx: FeatureContext): FeatureDecision { if (ctx.apiVersion 26) { return { mode: off, reason: api-version-not-ready, shouldRecordMetric: true }; } if (ctx.lowPowerMode) { return { mode: safe, reason: low-power-protect-frame, shouldRecordMetric: true }; } if (ctx.deviceShape foldable ctx.widthVp 720) { return { mode: full, reason: foldable-wide-layout, shouldRecordMetric: true }; } if (ctx.scene review) { return { mode: safe, reason: review-screenshot-stable-first, shouldRecordMetric: true }; } return { mode: compact, reason: default-compact, shouldRecordMetric: false }; } }这个写法的重点不是类名而是结果里带 reason。以后日志里看到 review-screenshot-stable-first就知道页面为什么选择安全模式不需要再翻一堆 if。案例一页面首屏不能因为新能力变慢第一类问题是后台刷新覆盖前台点击。用户刚点卡片进入详情后台刷新又把状态改了详情页拿到的参数可能不是用户看到的那一份。class StartupProbe { private marks: Recordstring, number {}; mark(name: string): void { this.marks[name] Date.now(); } cost(from: string, to: string): number { return (this.marks[to] ?? 0) - (this.marks[from] ?? 0); } } const probe new StartupProbe(); const policy new FeaturePolicy(); probe.mark(page-enter); const decision policy.decide({ apiVersion: 26, deviceShape: foldable, scene: preview, widthVp: 840, heightVp: 720, lowPowerMode: false }); probe.mark(policy-ready); console.info(feature-mode, decision.mode); console.info(feature-reason, decision.reason); console.info(policy-cost, probe.cost(page-enter, policy-ready));验收时我会看三个值mode 是否符合预期reason 是否能解释分支policy-cost 是否足够小。策略判断应该是轻量逻辑不能把耗时任务塞进去。案例二多设备切换时不能丢上下文第二类问题是过期态。卡片数据不能一直假装新鲜过期后要显示安全文案并把点击跳转改成重新加载。interface ViewSnapshot { route: string; selectedId: string; scrollOffset: number; featureMode: FeatureDecision[mode]; updatedAt: number; } class SnapshotStore { private current: ViewSnapshot | undefined; save(snapshot: ViewSnapshot): void { this.current { ...snapshot, updatedAt: Date.now() }; } restore(): ViewSnapshot | undefined { if (!this.current) { return undefined; } return { ...this.current }; } } const store new SnapshotStore(); store.save({ route: detail-preview, selectedId: card-10086, scrollOffset: 460, featureMode: decision.mode, updatedAt: Date.now() }); const restored store.restore(); console.info(restore-route, restored?.route); console.info(restore-feature-mode, restored?.featureMode);这里要防的不是“能不能保存一个对象”而是设备形态变化后页面上下文有没有跟着回来。比如折叠屏从半屏切到展开或者平板分屏宽度变化用户看到的内容不应该突然回到默认态。两种实现方式对比方案好处坑点我会放在哪里页面里直接 if/else写起来最快分支越来越多日志看不懂只适合临时验证独立 Policy 类能单测能记录 reason要先设计输入输出推荐用于正式代码Store 里直接保存全部状态恢复简单容易保存脏数据只保存必要字段Snapshot 分层保存边界清楚需要设计字段适合多设备和复杂页面我的选择是 Policy Snapshot。Policy 负责判断能力怎么开Snapshot 负责保存页面上下文。二者不要混在一起。封装成可以复用的入口export class HarmonyFeatureRuntime { private readonly policy new FeaturePolicy(); private readonly snapshots new SnapshotStore(); prepare(ctx: FeatureContext): FeatureDecision { return this.policy.decide(ctx); } saveView(snapshot: ViewSnapshot): void { this.snapshots.save(snapshot); } restoreView(): ViewSnapshot | undefined { return this.snapshots.restore(); } }这样封装之后页面只需要关心三件事准备策略、保存现场、恢复现场。以后换成另一个 HarmonyOS 7.0 能力点也可以沿用这套排查方式。检查清单API 版本边界有没有写清楚低版本是否有兜底。新能力是否会影响首屏、滑动、弹窗、页面返回。日志里能不能看出选择某个模式的原因。多设备切换后页面上下文能不能恢复。代码是否能单独跑策略测试而不是必须打开完整页面才知道结果。最后总结互动卡片刷新要按版本处理不要只按最新数据处理。卡片展示、点击意图和后台刷新各有边界只有把版本号和过期态写清楚才能避免卡片和页面互相打架。
返回列表