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

Sou*_*Dev 6 state flutter flutter-provider riverpod

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

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

编辑:复杂是指更多的字段(例如 50)以及列表和对象结构。你可以克隆它,但它很昂贵,而且在每一个小变化上都这样做感觉不自然/明智。这真的是预期的方式吗?有没有办法在仍然使用 StateNotifierProvider 的情况下进行克隆?

Ayo*_*oub 10

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

您可以使用freezedfreezed_annotation来帮助您在每次想要发出新状态时复制状态,您只需复制旧状态并更改您需要的内容即可。像这样的东西

state = state.copyWith(var1: "new var");
Run Code Online (Sandbox Code Playgroud)

这是使用冻结的复杂状态的示例

  1. 将freezed_annotation添加到您的dependencies
  2. 将freezebuild_runner添加到您的dev_dependencies
  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;
}
Run Code Online (Sandbox Code Playgroud)
  1. 在终端中运行此命令
flutter pub run build_runner build --delete-conflicting-outputs
Run Code Online (Sandbox Code Playgroud)
  1. freezed 将生成您的ComplexState以及其他一些有用的方法,例如copyWith()现在您可以在您的StateNotifier

以下是将 StateNotifier 与 Riverpod 一起使用的示例

flutter pub run build_runner build --delete-conflicting-outputs
Run Code Online (Sandbox Code Playgroud)

注意:freeze 还支持可为空和默认构造函数参数,您可以将其用于初始状态,请在其 pub.dev 页面上了解更多信息