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

Riverpod中两个StateProvider数据同步变更问题求助

Riverpod两个StateProvider列表同步变更的原因及解决办法

问题原因

这是Dart引用类型特性和不规范的状态修改方式共同导致的:

  • 若你曾将siblingsListProviderSD的列表直接赋值给deleteListSiblingsProviderSD(比如执行ref.read(deleteListSiblingsProviderSD.notifier).state = ref.read(siblingsListProviderSD)),两个Provider的状态会指向同一个列表实例,列表里的SiblingModel对象也是同一内存引用。修改其中一个列表内对象的属性时,另一个列表的对应对象因引用相同,属性值会同步变化。
  • 你直接修改state[index].fields?.name的操作,属于修改状态内部可变对象,未创建新的状态实例,既不会触发Riverpod的状态更新通知,还会因为引用共享导致其他持有该对象的地方同步变更。

解决办法

1. 确保两个Provider持有独立的对象引用

复制数据时必须创建列表和对象的深拷贝,而非直接赋值引用。首先给SiblingModel及内部类实现拷贝方法:

class SiblingModel {
  final Fields? fields;
  SiblingModel({this.fields});

  // 实现对象拷贝方法
  SiblingModel copyWith({Fields? fields}) {
    return SiblingModel(
      fields: fields ?? this.fields?.copyWith(),
    );
  }
}

class Fields {
  final String? name;
  Fields({this.name});

  Fields copyWith({String? name}) {
    return Fields(name: name ?? this.name);
  }
}

然后复制列表时生成新列表和对象副本:

final originalList = ref.read(siblingsListProviderSD);
ref.read(deleteListSiblingsProviderSD.notifier).state = 
  originalList.map((sibling) => sibling.copyWith()).toList();

2. 按Riverpod规范修改状态

修改状态时必须创建新的状态实例,触发Provider的状态更新,同时保证状态不可变性:

// 正确修改siblingsListProviderSD的状态
ref.read(siblingsListProviderSD.notifier).state = [
  ...ref.read(siblingsListProviderSD).asMap().entries.map((entry) {
    if (entry.key == index) {
      return entry.value.copyWith(
        fields: entry.value.fields?.copyWith(name: 'DUMMY NAME'),
      );
    }
    return entry.value;
  })
];

3. 推荐使用StateNotifierProvider(可选)

如果状态逻辑复杂,StateNotifierProvider更适合处理可变状态更新,强制遵循不可变规范:

class SiblingsListNotifier extends StateNotifier<List<SiblingModel>> {
  SiblingsListNotifier() : super([]);

  void updateSiblingName(int index, String newName) {
    state = [
      ...state.asMap().entries.map((entry) {
        if (entry.key == index) {
          return entry.value.copyWith(
            fields: entry.value.fields?.copyWith(name: newName),
          );
        }
        return entry.value;
      })
    ];
  }
}

final siblingsListProviderSD = StateNotifierProvider<SiblingsListNotifier, List<SiblingModel>>(
  (ref) => SiblingsListNotifier(),
);

调用方式:

ref.read(siblingsListProviderSD.notifier).updateSiblingName(index, 'DUMMY NAME');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 07:52:51