我有一个非常大的、复杂的应用程序,有很多页面和输入表单,有很多字段(文本、日期选择、组合框等),所以状态相当大。我正在从Provider切换到Riverpod,并且提议的状态管理方式似乎主要是StateNotifierProvider。但该状态是不可变的,这意味着您必须在每次更改时克隆完整的状态。我需要的是Providers ChangeNotifierProvider (Riverpod也有),以便能够拥有可变状态,并在触发侦听器上的重建时更多地控制。但Riverpod不鼓励使用ChangeNotifierProvider,这让我有点紧张。也许我没有真正理解StateNotifierProvider的概念。
问题是,我如何使用StateNotifierProvider来处理复杂的状态?真的有必要总是克隆国家吗?
编辑:我指的是更大数量的字段(例如50),也包括列表和对象结构。你可以克隆它,但它很昂贵,而且每做一点改变就这么做似乎不自然/不明智。这真的是我们想要的方式吗?是否有一种方法来克隆,而仍然使用StateNotifierProvider?
首先,我不建议使用ChangeNotifier
(可变状态)而不是StateNotifier
(不可变状态),因为在扑动中最实用的状态管理方法是使用不可变状态。
你可以使用freezed
和freezed_annotation
来帮助你复制状态,每次你想要释放一个新的,你只需要复制旧的状态和改变你需要的。像这样
state = state.copyWith(var1: "new var");
这里是一个使用冻结
的复杂状态的例子- 将freezed_annotation添加到
dependencies
在 - 创建您的状态
complex_state.dart
之类的,更改工厂构造器以满足您的需求
dev_dependencies
中添加frozen和build_runnerimport '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;
}
- 在终端中运行此命令
flutter pub run build_runner build --delete-conflicting-outputs
- frozen将生成
ComplexState
以及其他一些有用的方法,如copyWith()
,现在您可以在StateNotifier
中使用它们
下面是一个使用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页面