使用 Riverpod 登录 Flutter api

sta*_*014 4 flutter flutter-provider riverpod

我正在尝试使用 Riverpod 与 Laravel 后端登录。现在我只是从存储库返回 true 或 false。我设置了一个接受电子邮件和密码的表单。isLoading变量只是为了显示一个圆形指示器我已经运行了代码并且它可以工作,但不确定我是否正确使用了 Riverpod。有更好的方法吗?

auth_provider.dart

class Auth{
  final bool isLogin;
  Auth(this.isLogin);
}
class AuthNotifier extends StateNotifier<Auth>{
  AuthNotifier() : super(Auth(false));
  void isLogin(bool data){
    state = new Auth(data);
  }
}
final authProvider = StateNotifierProvider((ref) => new AuthNotifier());
Run Code Online (Sandbox Code Playgroud)

auth_repository.dart

class AuthRepository{
  static String url = "http://10.0.2.2:8000/api/";
  final Dio _dio = Dio();
  Future<bool> login(data) async {
    try {
        Response response = await _dio.post(url+'sanctum/token',data:json.encode(data));
        return true;
    } catch (error) {
        return false;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

登录屏幕.dart

void login() async{
  if(formKey.currentState.validate()){
    setState((){this.isLoading = true;});
    var data = {
      'email':this.email,
      'password':this.password,
      'device_name':'mobile_phone'
    };
    var result = await AuthRepository().login(data);
    if(result){
        context.read(authProvider).isLogin(true);
        setState((){this.isLoading = false;});
    }else
      setState((){this.isLoading = false;});
  }
}
Run Code Online (Sandbox Code Playgroud)

Vay*_*yth 9

由于我没有移动背景,最近才在最近的项目中使用 flutter+riverpod,所以我不能说这是最佳实践。但有几点我想指出:

  • 使用IAuthRepository存储库等接口。Riverpod 可以充当依赖注入。
final authRepository = Provider<IAuthRepository>((ref) => AuthRepository());
Run Code Online (Sandbox Code Playgroud)
  • 构建数据以发送到存储库中。如果可能的话,您应该将外部资源的表示、业务逻辑和显式实现分开。
  Future<bool> login(String email, String password) async {
    try {
        var data = {
          'email': email,
          'password': password,
          'device_name':'mobile_phone'
        };
        Response response = await _dio.post(url+'sanctum/token',data:json.encode(data));
        return true;
    } catch (error) {
        return false;
    }
  }
Run Code Online (Sandbox Code Playgroud)
  • 不要直接从演示/屏幕调用存储库。您可以将提供程序用于您的逻辑,它调用存储库
class AuthNotifier extends StateNotifier<Auth>{
  final ProviderReference ref;
  IAuthRepository _authRepository;

  AuthNotifier(this.ref) : super(Auth(false)) {
    _authRepository = ref.watch(authRepository);
  }

  Future<void> login(String email, String password) async {
    final loginResult = await_authRepository.login(email, password);
    state = Auth(loginResult);
  }
}

final authProvider = StateNotifierProvider((ref) => new AuthNotifier(ref));

Run Code Online (Sandbox Code Playgroud)
  • 在屏幕上,您可以调用提供者的login方法
login() {
  context.read(authProvider).login(this.email, this.password);
}
Run Code Online (Sandbox Code Playgroud)
  • 使用 Consumer 或 ConsumerWidget 来观察状态并决定构建什么。它还可以帮助Auth您创建其他状态,而不是使用 isLogin 作为状态。至少,我通常会创建一个 Abstract BaseAuthState,它派生为AuthInitialStateAuthLoadingStateAuthLoginStateAuthErrorState等。
class AuthNotifier extends StateNotifier<BaseAuthState>{
  ...
  AuthNotifier(this.ref) : super(AuthInitialState()) { ... }
  ...
}
Run Code Online (Sandbox Code Playgroud)
Consumer(builder: (context, watch, child) {
  final state = watch(authProvider.state);
  if (state is AuthLoginState) ...
  else if (state is AuthLoadingState) ...
  ...
})
Run Code Online (Sandbox Code Playgroud)