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

Flutter Riverpod中ListView.Builder无法正常更新的问题

问题:Flutter Riverpod结合ListView.Builder时列表无法更新

我正在用Flutter和flutter_riverpod开发应用,想结合ListView.Builder与Riverpod使用,但添加新用户时列表无法正常更新。作为新手急需解决建议。


初始实现及问题

Providers代码

final users_liste_pro = StateProvider((ref) {
  return liste;
});
final events_liste_pro = StateProvider((ref) {
  return events_liste;
});
final txt = StateProvider((ref) {
  return 0;
});

用户列表定义

var liste=[
  User(0,"adam","0000000","zone2","0000000","0000000000",null,false),
  User(1,"adam","0000000000","zone4","0000000","0000000000",null,false),
];

ConsumerWidget实现

class event_page extends ConsumerWidget {
  Event event ;
  event_page(this.event);
  @override
  Widget build(BuildContext context,WidgetRef ref) {

    final users = ref.watch(users_liste_pro);

    Size size = MediaQuery.of(context).size;
    return Scaffold(
      appBar: AppBar(
        title: Text("Event"),
      ),
      body: Container(
        width: size.width,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            SizedBox(height: 5,),
            Center(child: Text(event.name,style: TextStyle(fontSize: 30),)),
            Text("  Payed List :"),
            //临时解决方案:添加该变量
            Text(ref.watch(txt).toString()),
            Expanded(
              child: ListView.builder(
                  itemCount: users.length,
                  itemBuilder: (context, index) {
                    return eventpage_card(users[index],index);
                  }
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(onPressed: (){
        ref.read(users_liste_pro.notifier).state.add(User(400, "name", 'tele', "zone", "ville", "quartier",null, true));
        //临时解决方案:更新该int状态,否则列表的ref.watch不生效
        ref.read(txt.notifier).state++;
      },),
    );
  }
}

问题:直接调用state.add()修改列表后,ListView不会自动更新,只能通过更新另一个int类型的StateProvider强制触发UI重建,这种临时方案明显不合理。


改用StateNotifierProvider后的问题

尝试改用StateNotifierProvider解决,但列表长度仍无法更新:

class Userlistnotifier extends StateNotifier<List<User>>{   
  Userlistnotifier(): super([...liste]);

  void add(){
    state=[...state,User(400, "name", 'tele', "zone", "ville", "quartier",null, true)];
  }
}
final Userlist_provider=StateNotifierProvider<Userlistnotifier,List<User> >((ref) => Userlistnotifier());

// UI中使用
final users2 = ref.watch(Userlist_provider);

ListView.builder(
  itemCount: users2.length,//此处长度未更新
  itemBuilder: (context, index) {
    return eventpage_card(users2[index],index);
  }
),

解决方案

问题根源

  1. StateProvider失效原因:List是可变对象,调用add()仅修改了列表内部内容,但StateProvider的state引用未发生变化,Riverpod无法检测到状态变更,因此不会触发UI重建。
  2. StateNotifierProvider失效排查:大概率是未正确调用notifier的add()方法,或者UI监听逻辑有误。

正确实现方式

方式一:修复StateProvider的使用(适合简单场景)

不要直接修改现有列表,而是创建新列表替换原有state:

// FloatingActionButton的onPressed修改为
floatingActionButton: FloatingActionButton(onPressed: (){
  final currentUsers = ref.read(users_liste_pro.notifier).state;
  // 创建新列表,替换原有state
  ref.read(users_liste_pro.notifier).state = [
    ...currentUsers,
    User(400, "name", 'tele', "zone", "ville", "quartier", null, true)
  ];
  // 无需再更新txt状态
}),

方式二:正确使用StateNotifierProvider(推荐复杂场景)

确保状态更新时生成新列表,且UI正确调用notifier方法:

完整StateNotifier实现
// 遵守Dart命名规范:类名大驼峰,provider名小驼峰
class UserListNotifier extends StateNotifier<List<User>> {
  UserListNotifier() : super([...liste]);

  void addUser() {
    // 创建新列表,替换原有state(必须重新赋值state,不能修改原列表)
    state = [...state, User(400, "name", 'tele', "zone", "ville", "quartier", null, true)];
  }
}

final userListProvider = StateNotifierProvider<UserListNotifier, List<User>>(
  (ref) => UserListNotifier()
);
UI中正确使用
// 类名改为大驼峰EventPage
class EventPage extends ConsumerWidget {
  final Event event;
  // 添加const优化性能
  const EventPage(this.event);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final users = ref.watch(userListProvider);

    return Scaffold(
      appBar: AppBar(title: const Text("Event")),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const SizedBox(height: 5),
          Center(child: Text(event.name, style: const TextStyle(fontSize: 30))),
          const Text("  Payed List :"),
          Expanded(
            child: ListView.builder(
              itemCount: users.length,
              itemBuilder: (context, index) {
                // 组件名改为大驼峰EventPageCard
                return EventPageCard(users[index], index);
              },
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // 调用notifier的addUser方法触发状态更新
          ref.read(userListProvider.notifier).addUser();
        },
      ),
    );
  }
}

核心注意事项

  • Riverpod依赖状态引用变化触发更新:对于List、Map这类可变对象,必须生成新的实例替换原有state,不能直接修改内部内容。
  • StateNotifier中必须通过重新赋值state来更新状态,禁止直接修改原列表。
  • 遵循Dart命名规范:类名用大驼峰,变量/Provider名用小驼峰,提升代码可读性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 03:17:11