首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实现ChangeNotifier与StateNotifier

实现ChangeNotifier与StateNotifier
EN

Stack Overflow用户
提问于 2020-07-17 03:54:22
回答 3查看 4.2K关注 0票数 11

我非常熟悉提供程序包,并将其与ChangeNotifier相结合。

假设我有3个具有不同函数的getter和方法:

  1. 切换负载
  2. 切换图像加载
  3. 切换ObsecurePassword

使用ChangeNotifer

代码语言:javascript
复制
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,我只需要创建一个文件,只需调用像globalChangeNotifier.METHOD()这样的方法或像globalChangeNotifier.value这样的值。

但是现在,我已经了解了河荚包,在文档中,它使用的是StateNotifier

我想将以前的代码从ChangeNotifier迁移到StateNotifier。但据我理解,StateNotifier只能保存1种类型的数据,所以如果我想迁移上面的代码,我应该创建3个文件,比方说:

  1. provider_isloading.dart
  2. provider_isimageloading.dart
  3. provider_obsecurepassword.dart

使用StateNotifier

代码语言:javascript
复制
// 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());

我还需要创建一个文件来导出所有这些文件:

GlobalStateNotifer.dart

代码语言:javascript
复制
export './provider_loading.dart';
export './provider_imageloading.dart';
export './provider_obsecurepassword.dart';

我的问题是,正如我前面所解释的那样,这是最好的做法吗?

我的文件夹结构

EN

回答 3

Stack Overflow用户

发布于 2020-07-21 14:49:13

在使用Riverpod时,在它们提供的类上创建静态提供者是非常有意义的。从您的示例中,您可以重构为:

代码语言:javascript
复制
class IsImageLoading extends StateNotifier<bool> {
  IsImageLoading() : super(false);

  static final provider = StateNotifierProvider((ref) => IsImageLoading());

  void toggleImageLoading(bool value) {
    state = value;
  }
}

您还应该考虑是否需要您的提供程序在实际使用的类之外可用。有一点告诉我,你可能不会在任何地方使用你的密码提供者,但你的登录页面。考虑在该类中创建私有提供程序。

但是,如果您希望保持当前的方法,则可以创建一个包含3个bool值的类A和一个扩展StateNotifier<A>的类。

例如:

代码语言:javascript
复制
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
    }
  }
}

最后,我只想补充一下,可能有一种更好的方法来处理总体加载。考虑是否可以在Riverpod的AsyncValue中使用FutureProvider/StreamProvider,而不是手动切换加载状态。

票数 6
EN

Stack Overflow用户

发布于 2021-02-05 17:34:39

我认为您应该使用不可变的类,如下面的代码

代码语言:javascript
复制
@immutable
abstract class GlobalState {
  const GlobalState();
}

class IsImageLoading extends GlobalState {
  const IsImageLoading();
}

class IsLoading extends GlobalState {
  const IsLoading();
}

class IsObsecurePassword extends GlobalState {
  const IsObsecurePassword();
}

您的StateNotifier将如下所示

代码语言:javascript
复制
class GlobalStateNotifier extends StateNotifier<GlobalState> {
  GlobalStateNotifier(GlobalState state) : super(state);

  void changeState(GlobalState newState) {
    state = newState;
  }
}
票数 0
EN

Stack Overflow用户

发布于 2021-07-01 05:22:16

非常晚的响应,但我现在搜索的是相同的东西,我没有找到一种正确的方式来使用riverpod或StateNotifier,但是您可能应该像使用ChangeNotifier那样使用,或者对于flutter_bloc用户应该使用像flutter_bloc逻辑一样的.或者两者都是。

在本例中,根据我所读到的,我将只使用一个dart文件来放置所有这些代码,比如您的changenotifier类,并为IsImageLoading, isLoading, isObscurePassword创建简单的状态提供程序

在另一个MyViewProvider类中,您可以更改这些statesProvider的状态,或者不创建这些状态并在视图中直接更改状态。

代码语言:javascript
复制
final isImageLoadingProvider = StateProvider((ref) => false);

final isLoadingProvider = StateProvider((ref) => false);

final isObscurePasswordProvider = StateProvider((ref) => false);

final myViewProvider = Provider<MyViewProvider>((ref) {
  return MyViewProvider(ref.read);
});

class MyViewProvider {
  MyViewProvider(this._read);

  final Reader _read;

  void setLoading(bool value) {
    _read(isLoadingProvider).state = value;
  }

  void setImageLoading(bool value) {
    _read(isImageLoadingProvider).state = value;
  }

  void setObscurePassword() {
    final isObscure = _read(isLoadingProvider).state;
    _read(isObscurePasswordProvider).state = !isObscure;
  }
}

如有任何意见或改进,我将不胜感激。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62946841

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档