问题描述
我正在尝试使用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());
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;
}
}
}
login_screen.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;});
}
}
解决方法
由于我不是来自移动背景,只是最近在我最近的项目中使用了 flutter+riverpod,我不能说这是最佳实践。但有几点我想指出:
- 使用
IAuthRepository
等接口作为存储库。 Riverpod 可以充当依赖项注入。
final authRepository = Provider<IAuthRepository>((ref) => AuthRepository());
- 构建要发送到存储库中的数据。如果可能,您应该将外部资源的表示、业务逻辑和显式实现分开。
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;
}
}
- 不要直接从演示文稿/屏幕调用存储库。您可以为您的逻辑使用提供程序,它调用存储库
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));
- 在屏幕上,您可以调用提供者的
login
方法
login() {
context.read(authProvider).login(this.email,this.password);
}
- 使用 Consumer 或 ConsumerWidget 来观察状态并决定构建什么。
这也有助于代替
Auth
使用 isLogin 作为状态,您可以创建一些其他状态。至少,我通常会创建一个抽象的BaseAuthState
,它派生为AuthInitialState
、AuthLoadingState
、AuthLoginState
、AuthErrorState
等。
class AuthNotifier extends StateNotifier<BaseAuthState>{
...
AuthNotifier(this.ref) : super(AuthInitialState()) { ... }
...
}
Consumer(builder: (context,watch,child) {
final state = watch(authProvider.state);
if (state is AuthLoginState) ...
else if (state is AuthLoadingState) ...
...
})
,
我喜欢使用枚举或类作为身份验证状态,而不是使用 bool
enum AuthState { initialize,authenticated,unauthenticated }
和登录状态
enum LoginStatus { initialize,loading,success,failed }