首页 > 解决方案 > 我如何使用 StateNotifier Riverpod 来跟踪枚举值的变化

问题描述

我正在尝试使用 Riverpod stateNotifier 在用户身份验证期间跟踪枚举的更改以确定要显示的适当屏幕。例如 SignUp、SignIn、Homepage 或 Authenticating 屏幕,但我在命名构造函数中返回此错误:

超类“StateNotifier”没有零参数构造函数。尝试在“StateNotifier”中声明一个零参数构造函数,或在“StateNotifier”中显式调用不同的构造函数。我知道这里有一些我不明白的地方,但我无法弄清楚。

这是我的代码:

enum Status {
  unInitialized,
  unauthenticated,
  authenticating,
  authenticated,
  processing
}

class AuthWithEmailPassword extends StateNotifier<Status> {
  AuthWithEmailPassword() : super(Status.authenticated);

  Status _status = Status.authenticated;
  // AuthWithEmailPassword();
  UserServices _userServices = UserServices();

  FirebaseAuth _auth;
  UserModel _userModel;
  User _user;
  Status get status => _status;
  User get user => _user;
  UserModel get userModel => _userModel;

  //Name consturctor of this class
  @override
  AuthWithEmailPassword.initialize()
      : _auth = FirebaseAuth.instance{
    _status = Status.unInitialized;

    _auth.authStateChanges().listen((User value) async {
      _status = Status.unInitialized;

      if (value == null) {
        _status = Status.unauthenticated;

        print('user is signed out');
      } else {
        _userModel = await _userServices.getUserByUid(id: value.uid);
        _status = Status.authenticated;

        _user = value;
        print('user signed in');
      }
    });
  }}

标签: flutterdart

解决方案


您可以创建一个初始化函数并在 StateNotifierProvider 中调用它,而不是使用命名构造函数。

例如:

class AuthWithEmailPassword extends StateNotifier<Status> {
  AuthWithEmailPassword() : super(Status.authenticated);

  Status _status = Status.authenticated;
  Status get status => _status;

  final FirebaseAuth _auth = FirebaseAuth.instance;

  User _user;
  User get user => _user;

  UserModel _userModel;
  UserModel get userModel => _userModel;

  bool _init = false;
  late StreamSubscription _sub;

  void initialize() {
    if (_init) return;
    _status = Status.unInitialized;
    _sub = _auth.authStateChanges().listen(_listener);
    _init = true;
  }

  @override
  void dispose() {
    _sub.cancel();
    super.dispose();
  }

  Future<void> _listener(User? value) async {
    _status = Status.unInitialized;

    if (value == null) {
      _status = Status.unauthenticated;

      print('user is signed out');
    } else {
      _userModel = await _userServices.getUserByUid(id: value.uid);
      _status = Status.authenticated;

      _user = value;
      print('user signed in');
    }
  }
}

final authWithEmailPasswordProvider = StateNotifierProvider.autoDispose<AuthWithEmailPassword, Status>((_) {
  return AuthWithEmailPassword()..initialize();
});

推荐阅读