LarsDev
LarsDev

Reputation: 67

Flutter: Firebase Auth endless loop

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

Answers (2)

Peter Haddad
Peter Haddad

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

LarsDev
LarsDev

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

Related Questions