监听 helper class 中的变量变化
Listen for variable change in helper class
我正在尝试使用 firebase 为我的应用构建登录屏幕。我的登录功能运行良好,但我在登录失败时无法显示一些错误文本。
这是身份验证助手的代码class:
class AuthenticationService {
final FirebaseAuth _firebaseAuth;
String errorText = "";
AuthenticationService(this._firebaseAuth);
Stream<User> get authStateChanges => _firebaseAuth.authStateChanges();
Future<void> signOut() async {
await _firebaseAuth.signOut();
}
Future<String> signIn({String email, String password}) async {
try {
await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
return "Signed in";
}
on FirebaseAuthException catch (e) {
errorText = e.message;
return e.message;
}
}
Future<String> signUp({String email, String password}) async {
try {
await _firebaseAuth.createUserWithEmailAndPassword(email: email, password: password);
signIn(email: email, password: password);
return "Account created";
}
on FirebaseAuthException catch (e) {
errorText = e.message;
return e.message;
}
}
}
这是我的登录小部件的代码:
class SignIn extends StatefulWidget {
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
@override
State<StatefulWidget> createState() => _SignInWidgetState();
}
class _SignInWidgetState extends State<SignIn> {
final TextEditingController errorController = TextEditingController();
bool _isErrorContainerVisible = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sign In"),
),
body: Column(
children: [
TextField(
controller: widget.emailController,
decoration: InputDecoration(
labelText: "Email",
hintText: "example@gmail.com",
contentPadding: EdgeInsets.all(20.0),
),
),
TextField(
controller: widget.passwordController,
obscureText: true,
decoration: InputDecoration(
labelText: "Password",
hintText: "password",
contentPadding: EdgeInsets.all(20.0),
),
),
Visibility(
child: Container(
child: Text(
errorController.text,
style: TextStyle(
color: Colors.red,
),
),
padding: const EdgeInsets.all(20.0),
),
visible: _isErrorContainerVisible,
),
RaisedButton(
onPressed: () {
context.read<AuthenticationService>().signIn(
email: widget.emailController.text.trim(),
password: widget.passwordController.text.trim());
},
child: Text("Sign In"),
),
RaisedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return SignUp(widget.emailController.text.trim().toString(),
widget.passwordController.text.trim().toString());
}),
);
},
child: Text("Sign Up"),
)
],
),
);
}
}
基本上,如果 AuthenticationService
中的 errorText
出现错误(因为用户登录失败),我想做的是在 Visibility
小部件中显示文本。我意识到的问题是 signIn 方法是 Future,因此不会立即设置错误(我想我需要某种类型的变量侦听器)。我遵循了一些使用 TextEditingController
的示例 here,这种方法可以正常工作,但我需要再次单击登录按钮以显示错误,而不是第一次出现错误。任何帮助将不胜感激。
我最终找到了答案并希望分享以防其他人需要帮助。
基本上,我需要让我的 AuthenticationHelper
class 扩展一个 ChangeNotifier
,这样我就可以在发生任何 firebase 身份验证异常时调用 notifyListeners()
。
接下来,我需要使用 Provider 库创建一个 context.select
(documentation),它允许我监视 notifyListeners()
何时被调用。一旦检测到错误文本发生变化,我将 _isErrorContainerVisible 设置为 true 并显示错误。
我正在尝试使用 firebase 为我的应用构建登录屏幕。我的登录功能运行良好,但我在登录失败时无法显示一些错误文本。
这是身份验证助手的代码class:
class AuthenticationService {
final FirebaseAuth _firebaseAuth;
String errorText = "";
AuthenticationService(this._firebaseAuth);
Stream<User> get authStateChanges => _firebaseAuth.authStateChanges();
Future<void> signOut() async {
await _firebaseAuth.signOut();
}
Future<String> signIn({String email, String password}) async {
try {
await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
return "Signed in";
}
on FirebaseAuthException catch (e) {
errorText = e.message;
return e.message;
}
}
Future<String> signUp({String email, String password}) async {
try {
await _firebaseAuth.createUserWithEmailAndPassword(email: email, password: password);
signIn(email: email, password: password);
return "Account created";
}
on FirebaseAuthException catch (e) {
errorText = e.message;
return e.message;
}
}
}
这是我的登录小部件的代码:
class SignIn extends StatefulWidget {
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
@override
State<StatefulWidget> createState() => _SignInWidgetState();
}
class _SignInWidgetState extends State<SignIn> {
final TextEditingController errorController = TextEditingController();
bool _isErrorContainerVisible = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sign In"),
),
body: Column(
children: [
TextField(
controller: widget.emailController,
decoration: InputDecoration(
labelText: "Email",
hintText: "example@gmail.com",
contentPadding: EdgeInsets.all(20.0),
),
),
TextField(
controller: widget.passwordController,
obscureText: true,
decoration: InputDecoration(
labelText: "Password",
hintText: "password",
contentPadding: EdgeInsets.all(20.0),
),
),
Visibility(
child: Container(
child: Text(
errorController.text,
style: TextStyle(
color: Colors.red,
),
),
padding: const EdgeInsets.all(20.0),
),
visible: _isErrorContainerVisible,
),
RaisedButton(
onPressed: () {
context.read<AuthenticationService>().signIn(
email: widget.emailController.text.trim(),
password: widget.passwordController.text.trim());
},
child: Text("Sign In"),
),
RaisedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return SignUp(widget.emailController.text.trim().toString(),
widget.passwordController.text.trim().toString());
}),
);
},
child: Text("Sign Up"),
)
],
),
);
}
}
基本上,如果 AuthenticationService
中的 errorText
出现错误(因为用户登录失败),我想做的是在 Visibility
小部件中显示文本。我意识到的问题是 signIn 方法是 Future,因此不会立即设置错误(我想我需要某种类型的变量侦听器)。我遵循了一些使用 TextEditingController
的示例 here,这种方法可以正常工作,但我需要再次单击登录按钮以显示错误,而不是第一次出现错误。任何帮助将不胜感激。
我最终找到了答案并希望分享以防其他人需要帮助。
基本上,我需要让我的 AuthenticationHelper
class 扩展一个 ChangeNotifier
,这样我就可以在发生任何 firebase 身份验证异常时调用 notifyListeners()
。
接下来,我需要使用 Provider 库创建一个 context.select
(documentation),它允许我监视 notifyListeners()
何时被调用。一旦检测到错误文本发生变化,我将 _isErrorContainerVisible 设置为 true 并显示错误。