[英]Flutter and Firebase Authentication problem
Flutter fellow today I have a problem with the Firebase Authentication service. Flutter 小伙伴今天我遇到了 Firebase 身份验证服务的问题。 Well then let me explain the situation.
那么我来解释一下情况。 I have a page that let you select a type of user, if you select "Guest" you will push through the app's dashboard page
Nav()
without sign-in but if select "Sign-in" app will push you to the login page Login()
.我有一个页面可以让您选择一种用户类型,如果您选择“访客”,您将在不登录的情况下推送应用程序的仪表板页面
Nav()
但如果选择“登录”应用程序会将您推送到登录页面Login()
。
class SelectUser extends StatelessWidget {
const SelectUser({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFF20348F),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
padding: const EdgeInsets.all(15.0),
margin: const EdgeInsets.all(15.0),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(45),
),
child: TextButton(
child: const Text('Guest'),
onPressed: () {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => const Nav(),
),
(route) => false,
);
},
style: TextButton.styleFrom(
primary: const Color(0xFF20348F),
textStyle: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
)),
),
),
Container(
padding: const EdgeInsets.all(15.0),
margin: const EdgeInsets.all(15.0),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(45),
),
child: TextButton(
child: const Text('Sign-In'),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (contex) {
return const Login();
}));
},
style: TextButton.styleFrom(
primary: const Color(0xFF20348F),
textStyle: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
)),
),
),
],
),
),
);
}
}
In Nav()
I use BottomNavigationBarItem and have a several widget included Proflie()
inside.在
Nav()
我使用了BottomNavigationBarItem并且里面有一个包含Proflie()
小部件。 I already test the sign-up, sign-out and registration function everything is perfectly fine but when I try to be tricky in Proflie()
and I face...let's said the weird problem.我已经测试了注册、注销和注册功能,一切都很好,但是当我尝试在
Proflie()
变得棘手时,我面临......让我们说一个奇怪的问题。 First let's me show you the code in the Proflie()
.首先让我向您展示
Proflie()
的代码。
class Profile extends StatefulWidget {
const Profile({Key? key}) : super(key: key);
@override
_ProfileState createState() => _ProfileState();
}
class _ProfileState extends State<Profile> {
String? _email;
DateTime? _creationTime;
DateTime? _lastSignIn;
bool? _status;
@override
Widget build(BuildContext context) {
userStatus();
return userForm();
}
userStatus() {
FirebaseAuth.instance.authStateChanges().listen((event) {
if (event == null) {
_status = false;
} else {
_status = true;
_email = FirebaseAuth.instance.currentUser!.email;
_creationTime =
FirebaseAuth.instance.currentUser!.metadata.creationTime;
_lastSignIn =
FirebaseAuth.instance.currentUser!.metadata.lastSignInTime;
}
});
}
Widget userForm() {
if (_status == true) {
return Scaffold(
appBar: defaultAppBar('Profile'),
body: Center(
child: ListView(
padding: const EdgeInsets.all(20),
children: [
Container(
margin: const EdgeInsets.all(30),
child: Text(
'Email: $_email',
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
),
Container(
margin: const EdgeInsets.all(30),
child: Text(
'Creation Time: $_creationTime',
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
),
Container(
margin: const EdgeInsets.all(30),
child: Text(
'Last Sign-In: $_lastSignIn',
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
),
const SizedBox(height: 45),
button('Change password', 1),
const SizedBox(height: 18),
button('Change email', 2),
const SizedBox(height: 18),
button('Sign-out', 0),
],
),
),
);
} else {
return Center(
child: ListView(
padding: const EdgeInsets.all(14),
children: <Widget>[
const SizedBox(height: 100),
Container(
margin: const EdgeInsets.all(30),
child: const Center(
child: Text(
'Please sign-in to use this Feature',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
),
const SizedBox(height: 50),
button('Login', 3),
const SizedBox(height: 18),
button('Register', 4),
],
),
);
}
}
Widget button(String txt, int _nav) {
Color? _color = const Color(0xFF20348F);
if (_nav == 0) {
_color = Colors.red;
}
return TextButton(
style: TextButton.styleFrom(
primary: _color,
textStyle: const TextStyle(
fontSize: 20,
),
),
child: Text(txt),
onPressed: () {
if (_nav == 0) {
FirebaseAuth.instance.signOut();
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => const SelectUser(),
),
(route) => false,
);
} else {
Navigator.push(context, MaterialPageRoute(builder: (contex) {
if (_nav == 1) {
return const EditPass();
} else if (_nav == 2) {
return const EditEmail();
} else if (_nav == 3) {
return const Login();
} else {
return const Register();
}
}));
}
},
);
}
}
As you can see I'm trying to use userStatus()
to identify the "User" and "Guest" and that function I use FirebaseAuth.instance.authStateChanges().listen((event) to check user state in Firebase Authentication(Not really sure am I doing the right way if not please teach me how to check user state) if event == null
that mean no user sign-in right now. I'm just going to set _status = false
so the "Guest" should found the else
case in userForm()
. Otherwise _status = true
this mean user is signed-in and userForm()
should go to if (_status == true)
case.正如您所看到的,我正在尝试使用
userStatus()
来识别“用户”和“访客”,并且该功能我使用FirebaseAuth.instance.authStateChanges().listen((event)来检查 Firebase Authentication(Not真的确定我做对了,如果不是请教我如何检查用户状态)如果event == null
意味着现在没有用户登录。我只是要设置_status = false
所以“客人”应该在userForm()
找到else
情况。否则_status = true
这意味着用户已登录并且userForm()
应该转到if (_status == true)
情况。
Now the problem is when I success to sign-in on the Login()
.现在的问题是当我成功
Login()
。 In Profile()
I ended up got the else
case of userForm()
instead but that not all!在
Profile()
我最终得到了userForm()
的else
情况,但并非全部! When I hot reloaded the IDE it turn out now I'm in the if (_status == true)
case.当我热重载 IDE 时,结果现在我处于
if (_status == true)
情况。 Yeah like said it a weird problem the first time that app loaded the page it go to false case but when hot reloaded it turn to true case.是的,就像在应用程序第一次加载页面时说这是一个奇怪的问题,它会变成错误的情况,但是当热重新加载时,它会变成真实的情况。 I'm not so sure the error is from
Profile()
or Login()
.我不太确定错误来自
Profile()
或Login()
。 I'm just going leave the Login()
then.那我就要离开
Login()
。
class Login extends StatefulWidget {
const Login({Key? key}) : super(key: key);
@override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
final _formKey = GlobalKey<FormState>();
var _email = "";
var _password = "";
final emailController = TextEditingController();
final passwordController = TextEditingController();
bool _passwordVisible = true;
@override
void dispose() {
emailController.dispose();
passwordController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return formLogin();
}
Widget formLogin() {
return Scaffold(
appBar: defaultAppBar('Sign-In'),
body: Center(
child: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(32),
child: ListView(
children: [
buildEmail(),
const SizedBox(height: 24),
buildPassword('Password', 'Your password...'),
const SizedBox(height: 50),
button('Sign-in', 0),
const SizedBox(height: 24),
button('Sign-up', 1),
],
),
),
),
),
);
}
userLogin() async {
try {
await FirebaseAuth.instance
.signInWithEmailAndPassword(email: _email, password: _password);
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => const Nav(),
),
(route) => false,
);
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
backgroundColor: Colors.amber,
content: Text(
"Email not found",
style: TextStyle(fontSize: 16.0, color: Colors.black),
),
),
);
} else if (e.code == 'wrong-password') {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
backgroundColor: Colors.amber,
content: Text(
"Password incorrect",
style: TextStyle(fontSize: 16.0, color: Colors.black),
),
),
);
}
}
}
TextButton button(String txt, int nav) {
return TextButton(
style: TextButton.styleFrom(
primary: const Color(0xFF20348F),
textStyle: const TextStyle(
fontSize: 20,
),
),
child: Text(txt),
onPressed: () {
if (nav == 0) {
if (_formKey.currentState!.validate()) {
setState(() {
_email = emailController.text;
_password = passwordController.text;
});
userLogin();
}
} else {
_formKey.currentState!.reset();
Navigator.push(context, MaterialPageRoute(builder: (contex) {
return const Register();
}));
}
},
);
}
Widget buildEmail() {
return TextFormField(
decoration: const InputDecoration(
labelText: 'Email',
hintText: 'name@example.com',
prefixIcon: Icon(Icons.mail_outline),
border: OutlineInputBorder(),
errorStyle: TextStyle(color: Colors.redAccent, fontSize: 15),
),
controller: emailController,
validator: MultiValidator([
RequiredValidator(errorText: "Email is required"),
EmailValidator(errorText: "The format of email is incorrect")
]),
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.done,
);
}
Widget buildPassword(String _txt1, String _txt2) {
return TextFormField(
obscureText: _passwordVisible,
decoration: InputDecoration(
labelText: _txt1,
hintText: _txt2,
suffixIcon: GestureDetector(
onTap: () {
setState(() {
_passwordVisible = !_passwordVisible;
});
},
child: Icon(
_passwordVisible ? Icons.visibility : Icons.visibility_off,
),
),
prefixIcon: const Icon(Icons.vpn_key_outlined),
border: const OutlineInputBorder(),
errorStyle: const TextStyle(color: Colors.redAccent, fontSize: 15),
),
controller: passwordController,
validator: RequiredValidator(errorText: "Password is required"),
textInputAction: TextInputAction.done,
);
}
}
If you guy could help me I'd gladly appreciated.如果你能帮助我,我将不胜感激。
如果您可以创建一个 .gist,我会对您有所帮助,同样在您的个人资料页面中,我可以看到您在构建中监听用户更改的问题,将其添加到构建中非常不切实际,因为 flutter 会调用构建方法多次,构建应该是干净的,也有潜在的内存泄漏,因为你没有处理流。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.