如何使用Riverpods StateNotifierProvider处理复杂的状态



我有一个非常大的、复杂的应用程序,有很多页面和输入表单,有很多字段(文本、日期选择、组合框等),所以状态相当大。我正在从Provider切换到Riverpod,并且提议的状态管理方式似乎主要是StateNotifierProvider。但该状态是不可变的,这意味着您必须在每次更改时克隆完整的状态。我需要的是Providers ChangeNotifierProvider (Riverpod也有),以便能够拥有可变状态,并在触发侦听器上的重建时更多地控制。但Riverpod不鼓励使用ChangeNotifierProvider,这让我有点紧张。也许我没有真正理解StateNotifierProvider的概念。

问题是,我如何使用StateNotifierProvider来处理复杂的状态?真的有必要总是克隆国家吗?

编辑:我指的是更大数量的字段(例如50),也包括列表和对象结构。你可以克隆它,但它很昂贵,而且每做一点改变就这么做似乎不自然/不明智。这真的是我们想要的方式吗?是否有一种方法来克隆,而仍然使用StateNotifierProvider?

首先,我不建议使用ChangeNotifier(可变状态)而不是StateNotifier(不可变状态),因为在扑动中最实用的状态管理方法是使用不可变状态。

你可以使用freezedfreezed_annotation来帮助你复制状态,每次你想要释放一个新的,你只需要复制旧的状态和改变你需要的。像这样

state = state.copyWith(var1: "new var");

这里是一个使用冻结

的复杂状态的例子
  1. 将freezed_annotation添加到dependencies
  2. dev_dependencies中添加frozen和build_runner
  3. 创建您的状态complex_state.dart之类的,更改工厂构造器以满足您的需求
import 'package:freezed_annotation/freezed_annotation.dart';
part 'complex_state.freezed.dart';
@freezed
class ComplexState with _$ComplexState {
const ComplexState._();
const factory ComplexState({
required String var1,
required double var2,
required bool var3,
required int var4,
}) = _ComplexState;
}
  1. 在终端中运行此命令
flutter pub run build_runner build --delete-conflicting-outputs
  1. frozen将生成ComplexState以及其他一些有用的方法,如copyWith(),现在您可以在StateNotifier
  2. 中使用它们

下面是一个使用StateNotifier和Riverpod的例子

final complexStateNotifierProvider = StateNotifierProvider(
(ref) {
const initialState = ComplexState(
var1: "var1",
var2: 90.0,
var3: true,
var4: 90,
);
return ComplexStateNotifier(initialState);
},
);
abstract class ComplexStateEvent {}
class ComplexStateEventDoSomething implements ComplexStateEvent {}
class ComplexStateNotifier extends StateNotifier<ComplexState> {
ComplexStateNotifier(ComplexState state) : super(state);
void onEvent(ComplexStateEvent event) {
if (event is ComplexStateEventDoSomething) {
state = state.copyWith(var1: "new value");
}
}
}

注意: frozen还支持可为空的和默认的构造函数参数,你可以使用这些参数作为初始状态,更多信息请参阅其pub.dev页面

最新更新