如何使用 Riverpods StateNotifierProvider 处理复杂状态
How to handle complex state with Riverpods StateNotifierProvider
我有一个非常大、复杂的应用程序,其中包含许多页面,其中包含带有大量字段(文本、日期选择、组合框等)的输入表单,因此状态相当大。
我正在从 Provider 切换到 Riverpod,建议的状态管理方式似乎主要是 StateNotifierProvider。但是那个状态是不可变的,这意味着你必须在每次更改时克隆完整的状态。
我需要的是 Providers ChangeNotifierProvider(Riverpod 也有),以便能够拥有可变状态并更好地控制何时触发侦听器上的重建。
但是 Riverpod 不鼓励使用 ChangeNotifierProvider,这让我有点紧张。可能是我没有真正理解StateNotifierProvider这个概念。
那么问题来了,如何使用StateNotifierProvider来处理复杂的状态呢?真的有必要总是克隆状态吗?
编辑:复杂的是指更多的字段(例如 50 个)以及列表和对象结构。您可以克隆它,但它很昂贵,而且感觉 natural/smart 对每个小改动都这样做。这真的是预期的方式吗?有没有办法在仍然使用 StateNotifierProvider 的同时进行克隆?
首先,我不建议使用 ChangeNotifier
(可变状态)而不是 StateNotifier
(不可变状态),因为 flutter 中状态管理的最佳实用方法是使用不可变状态。
你可以使用freezed
和freezed_annotation
来帮助你复制状态,每次你想发出新的状态,你只需复制旧的状态并改变你需要的。
像这样
state = state.copyWith(var1: "new var");
这里是一个使用冻结的复杂状态的例子
- 将 freezed_annotation 添加到您的
dependencies
- 将 freezed and build_runner 添加到您的
dev_dependencies
- 创建你的状态
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;
}
- 运行终端中的这个命令
flutter pub run build_runner build --delete-conflicting-outputs
- freezed 将生成您的
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");
}
}
}
注意:freezed 还支持可空和默认构造函数参数,您可以将其用于初始状态,请在其 pub.dev 页面
上阅读更多内容
我有一个非常大、复杂的应用程序,其中包含许多页面,其中包含带有大量字段(文本、日期选择、组合框等)的输入表单,因此状态相当大。 我正在从 Provider 切换到 Riverpod,建议的状态管理方式似乎主要是 StateNotifierProvider。但是那个状态是不可变的,这意味着你必须在每次更改时克隆完整的状态。 我需要的是 Providers ChangeNotifierProvider(Riverpod 也有),以便能够拥有可变状态并更好地控制何时触发侦听器上的重建。 但是 Riverpod 不鼓励使用 ChangeNotifierProvider,这让我有点紧张。可能是我没有真正理解StateNotifierProvider这个概念。
那么问题来了,如何使用StateNotifierProvider来处理复杂的状态呢?真的有必要总是克隆状态吗?
编辑:复杂的是指更多的字段(例如 50 个)以及列表和对象结构。您可以克隆它,但它很昂贵,而且感觉 natural/smart 对每个小改动都这样做。这真的是预期的方式吗?有没有办法在仍然使用 StateNotifierProvider 的同时进行克隆?
首先,我不建议使用 ChangeNotifier
(可变状态)而不是 StateNotifier
(不可变状态),因为 flutter 中状态管理的最佳实用方法是使用不可变状态。
你可以使用freezed
和freezed_annotation
来帮助你复制状态,每次你想发出新的状态,你只需复制旧的状态并改变你需要的。
像这样
state = state.copyWith(var1: "new var");
这里是一个使用冻结的复杂状态的例子
- 将 freezed_annotation 添加到您的
dependencies
- 将 freezed and build_runner 添加到您的
dev_dependencies
- 创建你的状态
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;
}
- 运行终端中的这个命令
flutter pub run build_runner build --delete-conflicting-outputs
- freezed 将生成您的
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");
}
}
}
注意:freezed 还支持可空和默认构造函数参数,您可以将其用于初始状态,请在其 pub.dev 页面
上阅读更多内容