flutter - 实施 ChangeNotifier 与 StateNotifier
问题描述
我对Provider包非常熟悉,并将其与ChangeNotifier
.
假设我有 3 个具有不同功能的 getter 和方法:
- 切换加载
- 切换图像加载
- 切换 ObsecurePassword
使用 ChangeNotifer
import 'package:flutter/foundation.dart';
class GlobalChangeNotifier extends ChangeNotifier {
bool _isLoading = false;
bool _isImageLoading = false;
bool _isObsecurePassword = false;
bool get isLoading => _isLoading;
bool get isImageLoading => _isImageLoading;
bool get isObsecurePassword => _isObsecurePassword;
void setLoading(bool value) {
_isLoading = value;
notifyListeners();
}
void setImageLoading(bool value) {
_isImageLoading = value;
notifyListeners();
}
void setObsecurePassword(bool value) {
_isObsecurePassword = !value;
notifyListeners();
}
}
final globalChangeNotifier = GlobalChangeNotifier();
如果我正在使用ChangeNotifier
,我只需要创建 1 个文件并调用类似的方法globalChangeNotifier.METHOD()
或类似的值globalChangeNotifier.value
。
但是现在,我已经了解了Riverpod包,并且在文档中,它使用StateNotifier
.
我想将我以前的代码ChangeNotifier
从StateNotifier
. 但据我了解,StateNotifier 只能保存 1 种类型的数据,所以如果我想迁移上面的代码,我应该创建 3 个文件,比方说:
provider_isloading.dart
,provider_isimageloading.dart
和provider_obsecurepassword.dart
.
使用 StateNotifier
// provider_isloading.dart
class IsImageLoading extends StateNotifier<bool> {
IsImageLoading() : super(false);
void toggleImageLoading(bool value) {
state = value;
}
}
final isImageLoadingProvider = StateNotifierProvider((ref) => IsImageLoading());
// provider_isimageloading.dart
class IsLoading extends StateNotifier<bool> {
IsLoading() : super(false);
void toggleLoading(bool value) => state = value;
}
final isLoadingProvider = StateNotifierProvider((ref) => IsLoading());
// provider_obsecurepassword.dart
class IsObsecurePassword extends StateNotifier<bool> {
IsObsecurePassword() : super(false);
void toggleObsecurePassword(bool value) {
state = !value;
}
}
final isObsecurePasswordProvider = StateNotifierProvider((ref) => IsObsecurePassword());
而且我还需要创建 1 个文件来导出所有这些文件:
GlobalStateNotifer.dart
export './provider_loading.dart';
export './provider_imageloading.dart';
export './provider_obsecurepassword.dart';
我的问题是,按照我之前的解释,这是最好的做法吗?
我的文件夹结构
解决方案
使用 Riverpod 时,在它们提供的类上创建静态提供程序非常有意义。从您的示例中,您可以重构为:
class IsImageLoading extends StateNotifier<bool> {
IsImageLoading() : super(false);
static final provider = StateNotifierProvider((ref) => IsImageLoading());
void toggleImageLoading(bool value) {
state = value;
}
}
您还应该考虑是否需要您的提供者在您实际使用它们的课程之外可用。有些事情告诉我,除了登录页面之外,您可能不会在任何地方使用您的密码提供程序。考虑在该类中创建一个私有提供程序。
但是,如果您希望保持当前的方法,您可以创建一个A
包含 3 个 bool 值的类和一个扩展的类StateNotifier<A>
。
例如:
enum LoadingType { A, B, C }
class LoadingToggles {
bool A, B, C;
LoadingToggles({this.A = false, this.B = false, this.C = false});
static final provider = StateNotifierProvider.autoDispose((ref) => LoadingState(LoadingToggles()));
}
class LoadingState extends StateNotifier<LoadingToggles> {
LoadingState(LoadingToggles state) : super(state ?? LoadingToggles());
void toggle(LoadingType type) {
switch (type) {
case LoadingType.A:
state.A = !state.A;
break;
case LoadingType.B:
state.B = !state.B;
break;
case LoadingType.C:
state.C = !state.C;
break;
default:
// Handle error state
}
}
}
最后,只想补充一点,可能有更好的方法来处理整体加载。考虑是否可以将 FutureProvider/StreamProvider 与 Riverpod 的 AsyncValue 一起使用,而不是手动切换加载状态。
推荐阅读
- javascript - 页面关闭后网站如何显示通知?
- r - 如何根据属性分配分组?
- c# - 如何在 C# 中将字符串转换为字符串数组?
- reactjs - 如何解决注册功能中的“无效视图”错误?
- angular - Angular 8 App Design - 通用对象和大型计算功能
- java - 如果在资源管理器中打开,非空目录并不总是被删除
- python - python中scapy汇总函数的问题
- python - 如何将 Python Concurrent Futures 与装饰器一起使用
- c# - Moq 没有在继承树中调用正确的方法
- formatting - 将二进制数据/数字转换为易于记忆的格式