HarmonyOS 教学实战(三):列表分页、下拉刷新与性能优化(让列表真正“丝滑”)

在上一篇《HarmonyOS 教学实战(二)》中,我们已经让应用具备了:

  • 网络请求

  • 本地缓存

  • 离线兜底

  • 完整 Store 设计

但只要你的数据一多,列表就一定是性能重灾区

真实项目中,80% 的卡顿都来自:

❌ 列表一次性加载

❌ 下拉刷新逻辑混乱

❌ 滚动时频繁重建组件

这一篇,我们专门解决这些问题。


一、这一篇我们要解决哪些真实痛点?

围绕一个真实列表页面,完成 3 件事:

  1. 📄 列表分页加载(上拉加载更多)

  2. 🔄 下拉刷新(重新请求第一页)

  3. 🚀 列表性能优化(可复用组件 + 状态收敛)

完成后,你的列表会具备:

数据多也不卡、刷新快、滚动顺


二、先改接口:支持分页返回

假设后端接口升级为:

复制代码
GET /api/tasks?page=1&pageSize=10

返回格式:

复制代码
{
  "list": [
    { "id": 101, "title": "学习 HarmonyOS" }
  ],
  "hasMore": true
}

三、第一步:升级网络 Service(分页支持)

修改 service/TaskService.ets

复制代码
export interface PageResult<T> {
  list: T[]
  hasMore: boolean
}

export class TaskService {
  static async fetchTasks(
    page: number,
    pageSize: number
  ): Promise<PageResult<Task>> {
    const httpRequest = http.createHttp()

    const response = await httpRequest.request(
      `https://example.com/api/tasks?page=${page}&pageSize=${pageSize}`,
      { method: http.RequestMethod.GET }
    )

    const data = JSON.parse(response.result as string)

    return {
      list: data.list.map(item => new Task(item.id, item.title)),
      hasMore: data.hasMore
    }
  }
}

四、第二步:升级 Store(分页核心逻辑)

分页的核心逻辑必须放在 Store,而不是 UI。

修改 model/TaskModel.ets

复制代码
@ObservedV2
export class TaskStore {
  tasks: Task[] = []
  page: number = 1
  pageSize: number = 10
  hasMore: boolean = true
  loading: boolean = false
  refreshing: boolean = false

  async refresh() {
    if (this.refreshing) return

    this.refreshing = true
    this.page = 1

    const result = await TaskService.fetchTasks(this.page, this.pageSize)
    this.tasks = result.list
    this.hasMore = result.hasMore

    this.refreshing = false
  }

  async loadMore() {
    if (!this.hasMore || this.loading) return

    this.loading = true
    this.page++

    const result = await TaskService.fetchTasks(this.page, this.pageSize)
    this.tasks = this.tasks.concat(result.list)
    this.hasMore = result.hasMore

    this.loading = false
  }
}

教学重点

  • refresh():只管第一页

  • loadMore():只管追加

  • UI 只需要调用,不参与逻辑判断


五、第三步:页面中接入下拉刷新 & 上拉加载

修改 pages/Index.ets

复制代码
@ComponentV2
struct Index {
  @Local store = new TaskStore()

  @Once
  async init() {
    await this.store.refresh()
  }

  build() {
    Column() {
      Refresh({ refreshing: this.store.refreshing }) {
        List() {
          ForEach(this.store.tasks, (item: Task) => {
            TaskItem({ task: item, onDelete: () => {} })
          }, item => item.id.toString())

          if (this.store.hasMore) {
            ListItem() {
              Text(this.store.loading ? '加载中...' : '上拉加载更多')
                .onAppear(() => this.store.loadMore())
            }
          }
        }
      }
    }
  }
}

📌 onAppear 是分页加载的关键

📌 不需要监听滚动位置

📌 非常稳定


六、第四步:列表性能优化(重点)

1️⃣ 使用 @ReusableV2 优化列表项

复制代码
@ReusableV2
@ComponentV2
export struct TaskItem {
  @Param task: Task
  @Event onDelete: (id: number) => void

  build() {
    Row() {
      Text(this.task.title)
      Button("删除")
        .onClick(() => this.onDelete(this.task.id))
    }
  }
}

📌 ArkUI 会自动复用组件结构

📌 滚动时不会频繁销毁/重建


2️⃣ 避免 ListItem 中使用 @Local 状态

❌ 错误示例:

复制代码
@Local checked = false

会导致每个 Item 都维护自己的状态,极易卡顿。

✔ 正确做法:
状态上移到 Store 或 Model


3️⃣ 控制刷新粒度(状态收敛)

避免这样的写法:

复制代码
@Local store = new TaskStore() // 整个 store 变 → 全列表刷新

更优方式是:

  • 列表只依赖 tasks

  • loading 状态放在 footer


七、第五步:缓存 + 分页怎么配合?

推荐策略:

场景 行为
首次进入 读缓存 → 再 refresh
下拉刷新 丢弃缓存
上拉加载 不写缓存
退出页面 保存当前列表

📌 不要每一页都缓存

📌 缓存的是"可用数据",不是"中间态"


八、常见分页性能坑(必看)

❌ 坑 1:List + Column 嵌套

会导致全部子项提前创建

✔ 用 List + ListItem


❌ 坑 2:key 不稳定

复制代码
key = index // 非常危险

✔ 使用业务 id


❌ 坑 3:刷新 & 加载同时进行

✔ Store 中用标志位严格限制


九、现在你的 App 已经是"工业级列表"了

你已经具备:

✔ 分页加载

✔ 下拉刷新

✔ 状态隔离

✔ 高性能列表

✔ 可扩展 Store 结构

这已经是 90% 商业 App 列表的实现水平

相关推荐
一只大侠的侠37 分钟前
【Harmonyos】Flutter开源鸿蒙跨平台训练营 Day 2 鸿蒙跨平台开发环境搭建与工程实践
flutter·开源·harmonyos
heartbeat..3 小时前
JVM 性能调优流程实战:从开发规范到生产应急排查
java·运维·jvm·性能优化·设计规范
爱吃烤鸡翅的酸菜鱼3 小时前
CANN ops-nn卷积算子深度解析与性能优化
人工智能·性能优化·aigc
熊文豪3 小时前
CANN ops-nn 算子调试与性能优化
性能优化·cann·ops-nn
小镇敲码人3 小时前
华为CANN框架中HCCL仓库的全面解析:分布式通信的引擎
分布式·华为
王码码20354 小时前
Flutter for OpenHarmony 实战之基础组件:第三十一篇 Chip 系列组件 — 灵活的标签化交互
android·flutter·交互·harmonyos
黑码哥4 小时前
ViewHolder设计模式深度剖析:iOS开发者掌握Android列表性能优化的实战指南
android·ios·性能优化·跨平台开发·viewholder
坚果派·白晓明4 小时前
在鸿蒙设备上快速验证由lycium工具快速交叉编译的C/C++三方库
c语言·c++·harmonyos·鸿蒙·编程语言·openharmony·三方库
小镇敲码人4 小时前
深入剖析华为CANN框架下的Ops-CV仓库:从入门到实战指南
c++·python·华为·cann
lbb 小魔仙5 小时前
【HarmonyOS实战】OpenHarmony + RN:自定义 useFormik 表单处理
react native·harmonyos