新闻详情

新闻详情

首页 / 资讯中心 / 详情

HarmonyOS ArkUI 列表刷新为什么会闪:加载态、空态、错误态和旧数据怎么分开

发布时间:2026/9/1 6:41:47来源:尧图网络
HarmonyOS ArkUI 列表刷新为什么会闪:加载态、空态、错误态和旧数据怎么分开
HarmonyOS ArkUI 列表刷新为什么会闪加载态、空态、错误态和旧数据怎么分开先把问题说清楚列表刷新时最常见的问题是用户刚输入关键词列表马上清空然后加载一结束又显示新结果。网速慢一点时页面会在“旧数据、加载中、空状态”之间来回跳。这个问题表面上看是 UI 小毛病实际上多半是状态边界没有拆清楚。页面里同时有“正在加载”“已有旧数据”“新请求结果”“空状态”“错误状态”如果全部塞进一个布尔值里后面一定会乱。这篇只讲一个可复现问题列表刷新闪烁。我会先写一个容易出错的版本再写一个更稳的版本最后给出检查方法。环境和验证目标项说明技术方向HarmonyOS / ArkUI / ArkTS页面模型Stage 模型页面关注点列表刷新闪烁验证目标操作顺序变化时页面状态仍然可预测适用场景搜索页、筛选页、列表页、详情页返回刷新错误写法只用一个状态硬撑先看一个很常见的写法。代码短但后面排查很难。Entry Component struct BadCasePage { State loading: boolean false; State keyword: string ; State list: string[] []; State errorText: string ; private async reload() { this.loading true; this.errorText ; try { const result await this.mockRequest(this.keyword); this.list result; } catch (err) { this.errorText 加载失败; this.list []; } this.loading false; } private async mockRequest(keyword: string): Promisestring[] { return new Promise((resolve) { setTimeout(() resolve(keyword ? [keyword 结果] : []), 600); }); } build() { Column({ space: 12 }) { Search({ value: this.keyword, placeholder: 输入关键词 }) .onChange((value: string) { this.keyword value; this.reload(); }) if (this.loading) { Text(加载中) } else if (this.errorText.length 0) { Text(this.errorText) } else if (this.list.length 0) { Text(没有结果) } else { ForEach(this.list, (item: string) { Text(item).fontSize(16) }, (item: string) item) } } .padding(16) } }这段代码能跑但它有几个隐患- 请求慢一点时旧请求可能覆盖新请求- 空状态和加载状态挤在一起页面会闪- 错误后再搜索旧错误文案可能残留- 列表清空太早用户会看到内容突然消失。稳一点的拆法把页面状态拆成模型我的做法是把页面状态拆成明确的模型。不要让 loading、error、list 到处散着改。type PagePhase idle | loading | success | empty | error; class PageStateT { phase: PagePhase idle; data: T[] []; errorText: string ; requestVersion: number 0; startRequest(): number { this.phase loading; this.errorText ; this.requestVersion 1; return this.requestVersion; } applySuccess(version: number, data: T[]) { if (version ! this.requestVersion) { return; } this.data data; this.phase data.length 0 ? success : empty; } applyError(version: number, message: string) { if (version ! this.requestVersion) { return; } this.errorText message; this.phase error; } }这里的关键是 coderequestVersion/code。每次请求开始都拿一个版本号返回时只允许最新版本写回页面。这样输入很快时旧请求就不会覆盖新结果。把模型放回 ArkUI 页面Observed class RecipeSearchState extends PageStatestring {} Entry Component struct BetterCasePage { State keyword: string ; State state: RecipeSearchState new RecipeSearchState(); private async reload() { const version this.state.startRequest(); try { const result await this.mockRequest(this.keyword); this.state.applySuccess(version, result); } catch (err) { this.state.applyError(version, 加载失败请稍后再试); } } private async mockRequest(keyword: string): Promisestring[] { return new Promise((resolve) { setTimeout(() resolve(keyword ? [keyword 结果] : []), 600); }); } Builder buildContent() { if (this.state.phase loading) { LoadingProgress() } else if (this.state.phase error) { Text(this.state.errorText).fontColor(#C0372B) } else if (this.state.phase empty) { Text(没有匹配结果可以换个关键词) } else { ForEach(this.state.data, (item: string) { Text(item).fontSize(16).padding(12) }, (item: string) item) } } build() { Column({ space: 12 }) { Search({ value: this.keyword, placeholder: 输入关键词 }) .onChange((value: string) { this.keyword value; this.reload(); }) this.buildContent() } .padding(16) } }这种写法比一个 loading 变量长一点但排查问题更直接。页面到底是加载中、空结果、成功还是失败看 codephase/code 就够了。案例二旧数据要不要保留如果是下拉刷新我会保留旧数据只在顶部显示刷新状态如果是换关键词搜索我会进入 loading 或 skeleton。两种场景不要混用否则用户会以为当前列表就是新条件的结果。class QueryGuard { private currentVersion: number 0; next(): number { this.currentVersion 1; return this.currentVersion; } isLatest(version: number): boolean { return version this.currentVersion; } } Component struct GuardUsagePage { State guard: QueryGuard new QueryGuard(); State text: string ; private async runTask(keyword: string) { const version this.guard.next(); const result await this.remoteSearch(keyword); if (!this.guard.isLatest(version)) { return; } this.text result; } private async remoteSearch(keyword: string): Promisestring { return new Promise((resolve) { setTimeout(() resolve(结果 keyword), 300); }); } }这个小封装适合放到搜索、筛选、分页加载这些位置。只要有“后发请求应该覆盖先发请求”的场景就可以用。怎么验证没有写虚我会按这几步测1. 连续快速输入三个关键词看最后显示的是不是最后一个关键词的结果。2. 输入不存在的关键词看页面是否进入 empty而不是一直 loading。3. 模拟请求失败看错误文案出现后再次搜索是否能恢复。4. 切换筛选条件后看分页和旧列表是否被正确重置。5. 重复进入页面确认没有旧错误、旧空状态残留。如果这几步都过说明这套状态边界是能经得起操作顺序变化的。我会怎么选方案简单页面可以直接用 loading、list、errorText 三个状态不必上来就封装模型。但只要页面出现搜索、防抖、筛选、分页、错误重试我就会把状态收进一个模型里。原因很简单页面越复杂越不能让状态到处散着改。后面如果要复用可以把 codePageState/code 和 codeQueryGuard/code 单独抽出来。不同页面只需要换数据类型和请求方法状态流转还是同一套。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

STM32H5+FreeRTOS+lwIP实战:从CubeMX配置到网络透传与调试 2026/9/1 6:39:04

STM32H5+FreeRTOS+lwIP实战:从CubeMX配置到网络透传与调试

简介:面向STM32H5系列微控制器的FreeRTOS与LWIP集成工程,适用于需要轻量级网络通信的嵌入式开发者,尤其适合从ThreadX等商业RTOS向开源方案迁移的团队参考。项目基于STM32H563芯片,展示了如何用FreeRTOS管理并发任务,并…

阅读更多 →
Nexus 7二代ADB驱动安装全攻略:从USB调试到fastboot 2026/9/1 6:39:04

Nexus 7二代ADB驱动安装全攻略:从USB调试到fastboot

简介:Nexus7二代ADB驱动官方版是一份面向华硕Nexus7二代用户、开发者及刷机爱好者的USB调试驱动包,主要用于解决手机与电脑连接时无法识别设备、ADB通信失败等问题。安装后即可让电脑正确识别Nexus7平板,实现文件互传、应用调试、刷机与系统维…

阅读更多 →
LT6911C开发必备:HDMI转MIPI桥接芯片资料包深度解析 2026/9/1 6:39:04

LT6911C开发必备:HDMI转MIPI桥接芯片资料包深度解析

简介:面向LT6911C芯片硬件设计与软件调试的工程师,这套资料包覆盖原理图、PCB源文件、驱动代码、寄存器手册及官方Datasheet,适用于HDMI转MIPI/DP视频桥接方案的评估、原理图复用与PCB Layout参考。压缩包共14个文件,体积仅1.47MB…

阅读更多 →
四自由度机械臂全套建模与分析:运动学、轨迹规划与动力学仿真实战 2026/9/1 6:39:04

四自由度机械臂全套建模与分析:运动学、轨迹规划与动力学仿真实战

简介:面向四自由度机械臂设计与仿真学习者,这套资料将三维建模、运动学求解、轨迹规划、工作空间可视化和动力学仿真串成完整链路,尤其适合课程设计、毕业设计或入门科研参考。资源以一套统一构型为基准,包含SolidWorks装配体与6个…

阅读更多 →
最通用VNC客户端非他莫属 2026/9/1 6:39:04

最通用VNC客户端非他莫属

背景 windows时代,由于Windows远程桌面(RDP协议)的存在,VNC桌面一直坐冷板凳。随着信创的推进,VNC桌面也变得越来越热了。“不相信?” 只要你是麒麟、统信用户,毫不夸张的说,VNC桌面是连接这些操作系统最简…

阅读更多 →
github信息收集 2026/9/1 6:36:03

github信息收集

在漏洞挖掘的过程我们进行信息收集时,可以在GitHub和码云收集相关的信息、代码库,运气好的话可以在库中发现一些重要配置such as:数据库用户名和密码等 手工方法 github搜索语法: in:name baidu #标题搜索含有关键…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞