技术栈:Flutter(Dart) × OpenHarmony
目标:在 Day3(网络请求 + 列表)基础上,为清单列表补齐 下拉刷新 / 上拉加载 / 多状态提示,并新增 底部导航多页面切换,完成 OpenHarmony 真机验证与可复现提交。


零、阶段目标回顾

在 Day3 已完成 网络请求能力接入 + 数据清单列表构建 的基础上,本阶段(Day4~Day6)的目标不再是“能不能展示数据”,而是进一步贴近真实应用场景,重点解决两个问题:

  1. 列表交互能力不足

    • 仅支持下拉刷新(RefreshIndicator)
    • 不支持上拉加载、无更多数据、加载失败等状态
  2. 应用结构仍为单页面

    • 无法模拟真实 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 真机下拉刷新效果]

[图片占位:OpenHarmony 真机上拉加载效果]

[图片占位:No more data 状态提示效果]
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 时:列表不丢数据、不重置滚动位置
  • 上拉/下拉能力不受切换影响

[图片占位:底部导航栏 + 多页面切换效果]

[图片占位:切回 Posts 后列表状态保持效果]


关键改动清单(聚焦 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

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐