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

使用Riverpod Provider时ListView无法渲染组件的问题

解决Flutter Riverpod下ListView不实时更新的问题

问题根源

  1. 未监听Provider状态变化:你在build方法中使用ref.read(tasksProvider),该方法仅读取一次数据,不会监听后续状态变更,因此Provider更新时Widget不会触发重建。
  2. 不可变状态未触发更新:当前的tasksProvider返回固定的空列表实例,直接向该列表添加元素时,列表的引用未发生改变,Riverpod无法检测到状态变化,也就不会通知Widget更新。

解决方案

1. 改用NotifierProvider管理可变列表状态

将原只读Provider替换为支持状态更新的NotifierProvider,通过方法修改列表时生成新的列表实例,确保状态变化能被检测到:

@riverpod
class TasksNotifier extends _$TasksNotifier {
  @override
  List<Task> build() => [];

  // 新增Task的方法
  void addTask(Task newTask) {
    // 创建新列表,避免修改原实例
    state = [...state, newTask];
  }
}

2. 在Widget中用ref.watch监听状态变化

把build方法里的ref.read替换为ref.watch,这样Provider状态更新时,Widget会自动重建:

class TasksScreen extends StatefulHookConsumerWidget {
  const TasksScreen({super.key});

  @override
  ConsumerState<TasksScreen> createState() => _TasksScreenState();
}

class _TasksScreenState extends ConsumerState<TasksScreen> {
  @override
  Widget build(BuildContext context) {
    // 用watch监听状态变化,数据更新时自动重建Widget
    List<Task> tasks = ref.watch(tasksNotifierProvider);

    return Scaffold(
      body: ListView.builder(
        itemBuilder: (context, index) {
          return Task(task: tasks[index]);
        },
        itemCount: tasks.length,
      ),
    );
  }
}

3. 修改添加Task的逻辑

在SimpleDialog中添加Task时,通过Notifier的方法更新状态:

// 示例:Dialog中添加Task的逻辑
void _submitNewTask(Task newTask) {
  ref.read(tasksNotifierProvider.notifier).addTask(newTask);
  Navigator.pop(context);
}

额外优化

你原代码中的test方法属于冗余逻辑,直接使用ref.watch获取的列表渲染即可,无需额外转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 05:12:33