Flutter For OpenHarmony:列表交互闭环(pull_to_refresh)+ 底部导航多页面切换实践日志(Day4-6)
在 Day3(网络请求 + 列表)基础上,为清单列表补齐,并新增,完成 OpenHarmony 真机验证与可复现提交。
技术栈:Flutter(Dart) × OpenHarmony
目标:在 Day3(网络请求 + 列表)基础上,为清单列表补齐 下拉刷新 / 上拉加载 / 多状态提示,并新增 底部导航多页面切换,完成 OpenHarmony 真机验证与可复现提交。
零、阶段目标回顾
在 Day3 已完成 网络请求能力接入 + 数据清单列表构建 的基础上,本阶段(Day4~Day6)的目标不再是“能不能展示数据”,而是进一步贴近真实应用场景,重点解决两个问题:
-
列表交互能力不足
- 仅支持下拉刷新(RefreshIndicator)
- 不支持上拉加载、无更多数据、加载失败等状态
-
应用结构仍为单页面
- 无法模拟真实 App 的多页面切换场景
- 页面状态管理与工程结构有待演进
一:从 RefreshIndicator 升级为 pull_to_refresh(SmartRefresher)
1. 背景:Day3 的下拉刷新“能用但不完整”
Day3 的列表刷新来自 Flutter 原生 RefreshIndicator,它适合快速验证网络链路,但存在明显能力边界:
- ✅ 下拉刷新
- ❌ 上拉加载(分页)
- ❌ Footer 状态提示(加载中 / 失败 / 无更多数据)
- ❌ 刷新与分页状态机(状态容易散落在 UI 中)
因此 Day4 的改造目标是:引入可控的刷新/加载状态机,把列表交互补齐为闭环。
2. 关键改动:ListView 外层改为 SmartRefresher
核心结构从:
RefreshIndicator(onRefresh: ...) + ListView
升级为:
SmartRefresher(controller: ...) + ListView
并引入 RefreshController 统一管理状态。
3. 分页策略:使用 _page / _limit 做增量加载
为了让“上拉加载”有真实意义,本次实现了简单分页模型:
page:当前页码(从 1 开始)pageSize:单页条数(例如 20)hasMore:是否还有更多数据
请求使用:
GET /posts?_page=<page>&_limit=<pageSize>
并在上拉加载时追加数据。
4. 状态闭环:RefreshController 必须明确收口
在 SmartRefresher 中,下拉与上拉的结束状态必须显式回调,否则会出现:
- Header 一直转圈
- Footer 状态错乱(一直显示 noMore 或一直 loading)
因此在逻辑上明确调用:
- 刷新成功:
refreshCompleted() - 刷新失败:
refreshFailed() - 加载成功:
loadComplete() - 加载失败:
loadFailed() - 无更多数据:
loadNoData() - 刷新后重置 footer:
resetNoData()
5. 真机验证
验证要点:
- 下拉:触发请求,刷新动画正常结束
- 上拉:触发下一页请求并追加渲染
- 无更多:Footer 显示
No more data![[图片占位:OpenHarmony 真机下拉刷新效果]](https://i-blog.csdnimg.cn/direct/56d72c9c299441f49a2e1f218670937a.jpeg)
![[图片占位:OpenHarmony 真机上拉加载效果]](https://i-blog.csdnimg.cn/direct/ce7fb805e9cb4f6f839a1bd8ca793297.jpeg)
![[图片占位:No more data 状态提示效果]](https://i-blog.csdnimg.cn/direct/f2454ae760604972971112cbec67dd71.jpeg)
ps: 这里的 no more data 验证,其实没有刷出第六页,但是 page 还是 从 5 变成 6 了。后续需要 debug。
二:底部导航多页面切换(BottomNavigationBar + IndexedStack)
1. 动机:单页 Demo → 多页应用雏形
在列表交互闭环后,工程仍是“单页面”。为了模拟真实 App 结构,引入底部导航:
- Posts:网络列表页(pull_to_refresh)
- Profile:示例页
- About:示例页
2. 结构设计:MainShell 作为应用外壳
新增 MainShell:
- 底部导航栏:
BottomNavigationBar - 页面承载:
IndexedStack
选择 IndexedStack 的原因:
- 切换 Tab 时页面不销毁
- 列表页的分页数据、滚动位置保留
- 更贴近真实应用(避免反复重新请求)
3. 遇到的问题:const 上下文导致编译失败
在 flutter-oh 环境下遇到编译错误:
Cannot invoke a non-'const' constructor where a const expression is expected
定位结果:
- 某些页面/列表被放进
const上下文 AppBar(...)在该环境下不能作为 const 构造使用
修复策略:
- 移除
const Scaffold(...)等导致的 const 传播 - 只对安全组件使用 const(如
Text/Icon)
这是一次典型的“跨端编译差异”问题,也提示:在 flutter-oh 工程中应谨慎使用“深层 const”。
4. 真机验证
验证要点:
- 底部 3 个按钮可切换页面
- 切回 Posts 时:列表不丢数据、不重置滚动位置
- 上拉/下拉能力不受切换影响
![[图片占位:底部导航栏 + 多页面切换效果]](https://i-blog.csdnimg.cn/direct/7b60670116d44cd288eed7a632de0c3c.jpeg)
![[图片占位:切回 Posts 后列表状态保持效果]](https://i-blog.csdnimg.cn/direct/cb6a214c55ba45cca6046268076e3f9b.jpeg)
关键改动清单(聚焦 pull_to_refresh + 底部按钮)
pull_to_refresh
- 替换 RefreshIndicator → SmartRefresher
- 引入 RefreshController 统一管理刷新/加载状态
- 增加分页参数:page/pageSize/hasMore
- 补齐状态闭环:refreshCompleted/refreshFailed/loadComplete/loadFailed/loadNoData/resetNoData
- 空/错场景使用 AlwaysScrollableScrollPhysics 保证可下拉
底部导航多页面
- 新增 MainShell(BottomNavigationBar)
- 使用 IndexedStack 保留页面状态
- 修复 const 上下文导致的 AppBar 编译错误
下一步进行整理,然后尝试像实际产品改进。
欢迎加入开源鸿蒙跨平台社区
https://openharmonycrossplatform.csdn.net
更多推荐


所有评论(0)