Flutter + Firebase Throwing Unhandled Exception: This widget has been unmounted Error Using Navigator to change view

4,221

You have to dispose the listener in dispose method of stateful widget like this:

class Sample extends StatefulWidget {
  @override
  _SampleState createState() => _SampleState();
}

class _SampleState extends State<Sample> {
  StreamSubscription<User> _listener;

  @override
  Widget build(BuildContext context) {
    return Container();
  }

  @override
  void initState() {
    _listener = FirebaseAuth.instance.authStateChanges().listen((User user) {
      if (user == null) {
        print('User is currently signed out!');
        if (AuthScreen.id != '/AuthScreen') {
          Navigator.pushReplacement(
              context,
              MaterialPageRoute(
                  builder: (BuildContext context) => AuthScreen()));
        } else {
          print("Already on auth screen");
        }
      } else {
        //Send to welcome screen
        print('User is signed in!');
        Navigator.pushReplacement(
            context,
            MaterialPageRoute(
                builder: (BuildContext context) => WelcomeScreen()));
      }
    });
    super.initState();
  }

  @override
  void dispose() {
    _listener.cancel();
    super.dispose();
  }
}

Share:
4,221
Sebastian Flores
Author by

Sebastian Flores

Updated on December 28, 2022

Comments

  • Sebastian Flores
    Sebastian Flores over 1 year

    I have a firebase driven Flutter app that is working but throwing errors.

    What I expected, when the app is open the user has to login using an email and password, if the login succeeds then they are taken the a new view called WelcomeScreen.

    What is happening, the users are being taken to a welcome screen after logging in but I get the following errors

    [VERBOSE-2:ui_dart_state.cc(186)] Unhandled Exception: This widget has been unmounted, so the State no longer has a context (and should be considered defunct).
    Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.
    #0      State.context.<anonymous closure> (package:flutter/src/widgets/framework.dart:1088:9)
    #1      State.context (package:flutter/src/widgets/framework.dart:1094:6)
    #2      _AuthScreenState.initState.<anonymous closure> (package:autos_latinos/screens/auth_screen.dart:81:35)
    #3      _rootRunUnary (dart:async/zone.dart:1362:47)
    #4      _CustomZone.runUnary (dart:async/zone.dart:1265:19)
    #5      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1170:7)
    #6      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
    #7      _DelayedData.perform (dart:async/stream_impl.dart:591:14)
    #8      _StreamImplEvents.handleNext (dart:async/stream_impl.dart:706:11)
    #9      _PendingEvents.schedule.<anonymous closur<…>
    

    It seems to be pointing to this part here in my code which I use to track authStateChanges from firebase:

    FirebaseAuth.instance.authStateChanges().listen((User user) {
          if (user == null) {
            print('User is currently signed out!');
            if(AuthScreen.id != '/AuthScreen'){
              Navigator.pushReplacement(context, MaterialPageRoute(builder: (BuildContext context) => AuthScreen()));
            }else{
              print("Already on auth screen");
            }
    
    
          } else {
            //Send to welcome screen
            print('User is signed in!');
            Navigator.pushReplacement(context, MaterialPageRoute(builder: (BuildContext context) => WelcomeScreen()));
          }
        });
    

    Any Advice on how to prevent this error is much appreciated.