9

我对Provider包非常熟悉,并将其与ChangeNotifier.

假设我有 3 个具有不同功能的 getter 和方法:

  1. 切换加载
  2. 切换图像加载
  3. 切换 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.

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

  1. provider_isloading.dart,
  2. provider_isimageloading.dart
  3. 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';

我的问题是,按照我之前的解释,这是最好的做法吗?

我的文件夹结构

我的文件夹结构

4

3 回答 3

6

使用 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 一起使用,而不是手动切换加载状态。

于 2020-07-21T14:49:13.857 回答
0

很晚的响应,但我现在正在搜索相同的东西,我没有找到使用 Riverpod 或 StateNotifier 的正确方法,但可能你应该像使用 ChangeNotifier 一样使用,或者对于 flutter_bloc 用户,他们应该像使用 flutter_bloc 逻辑一样使用。 .. 或两者。

对于这种情况,根据我的阅读,我将只使用一个 dart 文件来放置所有代码,比如你的 changenotifier 类,并为IsImageLoading, isLoading, isObscurePassword

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


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;
  }
}

我将不胜感激任何意见或改进

于 2021-07-01T05:22:16.983 回答
0

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

@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 将如下所示

class GlobalStateNotifier extends StateNotifier<GlobalState> {
  GlobalStateNotifier(GlobalState state) : super(state);

  void changeState(GlobalState newState) {
    state = newState;
  }
}
于 2021-02-05T17:34:39.563 回答