Flutter 列表 + Riverpod 架构实战 —— 从 setState 到状态驱动列表的工程落地

Flutter 列表真正的威力,不在 ListView,而在:

👉 列表 = 状态的投影结果


一、为什么 Flutter 列表必须配状态管理?

新手写法:

Dart 复制代码
setState(() {
  list.addAll(newData);
});

问题:

  • 业务逻辑混在 UI
  • 无法复用
  • 无法测试
  • 分页、错误、加载状态混乱

企业级目标:

👉 UI 只关心"状态"

👉 所有列表行为 = 状态机

二、列表的标准状态建模(架构核心)

一个工程级列表,最少包含:

Dart 复制代码
class ListState<T> {
  final List<T> items;
  final bool isLoading;
  final bool isRefreshing;
  final bool hasMore;
  final String? error;

  const ListState({
    this.items = const [],
    this.isLoading = false,
    this.isRefreshing = false,
    this.hasMore = true,
    this.error,
  });
}

👉 这是 Flutter 列表的"领域模型(Domain State)"。

三、Riverpod Controller 层(替代 ViewModel)

Dart 复制代码
class UserListController extends StateNotifier<ListState<User>> {
  UserListController() : super(const ListState());

  Future<void> refresh() async {
    state = state.copyWith(isRefreshing: true);
    final data = await repo.fetch(page: 1);
    state = state.copyWith(
      items: data,
      isRefreshing: false,
      hasMore: true,
    );
  }

  Future<void> loadMore() async {
    if (!state.hasMore || state.isLoading) return;

    state = state.copyWith(isLoading: true);
    final data = await repo.fetchNext();
    state = state.copyWith(
      items: [...state.items, ...data],
      isLoading: false,
      hasMore: data.isNotEmpty,
    );
  }
}
Dart 复制代码
final userListProvider =
  StateNotifierProvider<UserListController, ListState<User>>(
    (ref) => UserListController(),
  );

👉 这里就是 MVVM / MVI 的 ViewModel / Reducer 层。

四、UI 层(纯渲染,不写业务)

Dart 复制代码
class UserListPage extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final state = ref.watch(userListProvider);
    final controller = ref.read(userListProvider.notifier);

    return RefreshIndicator(
      onRefresh: controller.refresh,
      child: ListView.builder(
        itemCount: state.items.length + 1,
        itemBuilder: (context, index) {
          if (index == state.items.length) {
            return _Footer(state);
          }
          return UserItem(state.items[index]);
        },
      ),
    );
  }
}
Dart 复制代码
class _Footer extends StatelessWidget {
  final ListState state;

  const _Footer(this.state);

  @override
  Widget build(BuildContext context) {
    if (state.isLoading) {
      return Center(child: CircularProgressIndicator());
    }
    if (!state.hasMore) {
      return Center(child: Text("没有更多了"));
    }
    return SizedBox.shrink();
  }
}

✔ UI = 纯函数

✔ 可测试

✔ 可替换

✔ 可维护

五、滚动触底触发分页

Dart 复制代码
final scrollController = ScrollController();

scrollController.addListener(() {
  if (scrollController.position.pixels >
      scrollController.position.maxScrollExtent - 200) {
    ref.read(userListProvider.notifier).loadMore();
  }
});

👉 滚动是输入

👉 Controller 决定状态变化

👉 UI 只是结果

六、这套架构解决了什么?

问题 解决
setState 混乱 状态集中管理
分页难写 行为模型化
异常难处理 error 状态
UI 不可测 Controller 可单测
列表难复用 Domain State 可复用

👉 这是"架构级列表"。

七、架构总结

Flutter 列表的终极形式:

Dart 复制代码
Input(滚动/点击)
   ↓
Controller(Riverpod)
   ↓
State(列表领域模型)
   ↓
ListView(UI渲染)
相关推荐
见山是山-见水是水30 分钟前
鸿蒙flutter第三方库适配 - 文件加密工具
flutter·华为·harmonyos
麒麟ZHAO1 小时前
鸿蒙flutter第三方库适配 - 文件对比工具
数据库·redis·flutter·华为·harmonyos
weixin_443478511 小时前
Flutter组件学习之图表
学习·flutter·信息可视化
猿饵块1 小时前
flutter--基础环境安装
flutter
见山是山-见水是水2 小时前
Flutter 框架跨平台鸿蒙开发 - 电子发票智能管理
flutter·华为·harmonyos
MonkeyKing3 小时前
Flutter刷新机制与重建优化
flutter
空中海3 小时前
4.4 动态与嵌套路由
flutter
2401_839633914 小时前
鸿蒙flutter第三方库适配 - 存储空间分析
flutter·华为·harmonyos
加农炮手Jinx4 小时前
Flutter 三方库 better_commit 的鸿蒙化适配指南 - 实现具备语义化提交规范与自动化交互的 Git 工作流插件、支持端侧版本工程的高效规范化审计实战
flutter·harmonyos·鸿蒙·openharmony·better_commit
空中海4 小时前
3.3 第三方框架
flutter·dart