Reputation: 67
I want to build a Flutter login screen working with Firebase Auth. I posted the Code below. When i run the App, the _switchToHomePage()
method is called endless. So the app keeps opening an new HomeScreen until I close the app.
Thanks for help!
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/services.dart';
import 'home_page.dart';
import 'register.dart';
import 'error_dialog.dart';
class LoginForm extends StatefulWidget {
@override
State<StatefulWidget> createState() => _LoginFormState();
}
class _LoginFormState extends State<LoginForm> {
final emailController = TextEditingController();
final passwordController = TextEditingController();
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
bool _hidePassword = true;
void _checkUserIsLoggedIn() {
_firebaseAuth.currentUser().then((firebaseUser) {
if (firebaseUser == null) {
print('no user logged in');
} else {
print('User logged in');
_switchToHomePage();
}
});
}
void _switchToHomePage() {
print('switching to home page...');
Navigator.push(
context, MaterialPageRoute(builder: (context) => HomePage()));
this.deactivate();
}
void _login() {
String email = emailController.text;
String password = passwordController.text;
_firebaseAuth
.signInWithEmailAndPassword(email: email, password: password)
.then((firebaseUser) {
if (firebaseUser != null) {
print('Login succesfull');
_switchToHomePage();
} else {
throw Exception('FirebaseUser is null');
}
}).catchError((exception) {
//TODO make better error messages
print(exception.message);
ErrorDialog(
context: this.context,
title: 'Error',
message: exception.message);
});
}
void _showRegisterScreen() {
Navigator.push(
context, MaterialPageRoute(builder: (context) => RegisterForm()));
}
@override
Widget build(BuildContext context) {
_checkUserIsLoggedIn();
return Scaffold(
appBar: AppBar(title: Text('Login')),
body: ListView(
padding: EdgeInsets.fromLTRB(15, 30, 15, 0),
children: <Widget>[
Padding(padding: EdgeInsets.only(top: 60)),
Text(
'placeholder',
style: TextStyle(
color: Colors.teal,
fontSize: 40,
),
),
Padding(padding: EdgeInsets.only(top: 60)),
Padding(padding: EdgeInsets.only(top: 40)),
TextField(
controller: emailController,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
prefixIcon: Icon(Icons.email),
labelText: 'E-Mailadresse',
border: UnderlineInputBorder()),
),
Padding(padding: EdgeInsets.only(top: 20)),
TextField(
controller: passwordController,
obscureText: _hidePassword,
decoration: InputDecoration(
labelText: 'Passwort',
border: UnderlineInputBorder(),
prefixIcon: Icon(Icons.security),
suffixIcon: IconButton(
icon: Icon(Icons.remove_red_eye),
color: _hidePassword
? Theme.of(context).primaryColor
: Colors.grey,
onPressed: () => this.setState(() {
_hidePassword = !_hidePassword;
}),
)),
),
Padding(padding: EdgeInsets.only(top: 5)),
Container(
child: FlatButton(
onPressed: () => print('Forgot password'),
child: Text(
'Passwort vergessen?',
style: TextStyle(color: Theme.of(context).primaryColor),
),
),
width: double.infinity,
alignment: Alignment.centerRight,
),
Padding(padding: EdgeInsets.only(top: 40)),
RaisedButton(
onPressed: _login,
color: Theme.of(context).primaryColor,
child: Text(
'Login',
style: TextStyle(color: Colors.white),
),
),
Padding(padding: EdgeInsets.only(top: 20)),
FlatButton(
onPressed: _showRegisterScreen,
child: Text(
'Neuen Account erstellen',
style: TextStyle(
fontSize: 16,
color: Theme.of(context).accentColor,
),
),
)
],
));
}
}
Upvotes: 0
Views: 858
Reputation: 80924
The reason you get that, is because _checkUserIsLoggedIn();
which contains navigation to the HomePage
is the first method inside build
method. Inside the build()
method you have setState()
on the TextField
, therefore everytime the state is changing then the build()
method is getting called and _checkUserIsLoggedIn()
is also getting called. To solve that try the following:
@override
initState() {
super.initState();
_firebaseAuth.currentUser().then((firebaseUser) {
if (firebaseUser == null) {
print('no user logged in');
} else {
print('User logged in');
_switchToHomePage();
}
});
}
Inside the lifecycle method initState()
check if the user is logged in and navigate to the HomePage
. Also remove the method _checkUserIsLoggedIn();
from the build
method
Upvotes: 1
Reputation: 67
I just solved it. I replaced:
Navigator.push(
context, MaterialPageRoute(builder: (context) => RegisterForm()));
with
Navigator.pushAndRemoveUntil(
context, MaterialPageRoute(builder: (context) => HomePage()), (e) => false);
Upvotes: 0