You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Riverpod NotifierProvider中监听数组单个元素避免全量重建

解决Riverpod待办事项列表局部重建问题

当前的实现中,每次单个待办项的状态变化都会触发整个TodoListView重建,要实现仅变化的待办项组件单独重建,可以通过拆分独立组件+精准监听的方式解决,具体方案如下:

步骤1:拆分单个待办项为独立组件

将每个待办项的UI抽成单独的ConsumerWidget,在组件内部通过select方法精准监听对应ID的待办项变化:

class TodoItem extends ConsumerWidget {
  final String todoId;

  const TodoItem({super.key, required this.todoId});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // 仅监听当前ID对应的待办项,只有该待办项变化时才重建组件
    final todo = ref.watch(
      todosProvider.select((todos) => todos.firstWhere((t) => t.id == todoId)),
    );

    // 可选:处理待办项已被删除的情况(需引入collection包使用firstWhereOrNull)
    // final todo = ref.watch(
    //   todosProvider.select((todos) => todos.firstWhereOrNull((t) => t.id == todoId)),
    // );
    // if (todo == null) return const SizedBox.shrink();

    return CheckboxListTile(
      value: todo.completed,
      onChanged: (_) => ref.read(todosProvider.notifier).toggle(todoId),
      title: Text(todo.description),
    );
  }
}

步骤2:优化列表组件的监听范围

修改原TodoListView,仅监听待办项的ID列表(对应添加/删除操作),单个待办项的状态变化不会触发列表组件重建,同时使用ListView.builder提升列表性能:

class TodoListView extends ConsumerWidget {
  const TodoListView({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // 仅监听待办项ID列表的变化(添加/删除待办时才重建)
    final todoIds = ref.watch(
      todosProvider.select((todos) => todos.map((t) => t.id).toList()),
    );

    return ListView.builder(
      itemCount: todoIds.length,
      itemBuilder: (context, index) => TodoItem(todoId: todoIds[index]),
    );
  }
}

方案说明

  • 局部监听:每个TodoItem通过select方法只关注自身对应的待办项,只有当该待办项的completed或description变化时,才会触发自身重建,其他待办项的变化不会影响它。
  • 列表优化:TodoListView现在仅监听待办项的ID列表,只有添加/删除待办时才会重建,避免了单个待办状态变化导致的全列表刷新。
  • 性能提升:ListView.builder只会构建当前可见的待办项组件,进一步优化了大列表的性能。

内容的提问来源于stack exchange,提问作者user1949350

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 18:27:25