Home > Back-end >  Flutter Navigator.of(context).pushReplacementNamed throws :"Unhandled Exception: Null check ope
Flutter Navigator.of(context).pushReplacementNamed throws :"Unhandled Exception: Null check ope

Time:05-23

So, I started to make a Flutter App with sdk: ">=2.16.2 <3.0.0" and Firebase Integration. I have the following code on main.dart for "authStateChanges()":

if (snapshot.connectionState == ConnectionState.done) {
   FirebaseAuth.instance.authStateChanges().listen((User? user) {
      if (user == null) {
         Navigator.of(context).pushReplacementNamed('login');
      } else {
         Navigator.of(context).pushReplacementNamed('home');
      }
   });
}

It works at the first time when loading the app, but If the user signs in (or out), then the "Unhandled Exception: Null check operator used on a null value" occurs on Navigator.

FLutter Exception ocurred

Here is the full main.dart code:

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:pollux_android/src/pages/error_page.dart';
import 'package:pollux_android/src/pages/loading_page.dart';
import 'package:pollux_android/src/routes/routes.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
  final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
}

class _MyAppState extends State<MyApp> {
  final Future<FirebaseApp> _initialization = Firebase.initializeApp();
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      routes: polluxRoutes,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: mainScreen(),
    );
  }

  mainScreen() {
    return FutureBuilder(
      future: _initialization,
      builder: (context, snapshot) {
        if (snapshot.hasError) {
          return const ErrorPage(
            errorMessage: 'Unknown error',
          );
        }

        if (snapshot.connectionState == ConnectionState.done) {
          FirebaseAuth.instance.authStateChanges().listen((User? user) {
            if (user == null) {
              Navigator.of(context).pushReplacementNamed('login');
            } else {
              Navigator.of(context).pushReplacementNamed('home');
            }
          });
        }

        return const LoadingPage();
      },
    );
  }
}

I don't get why it fails to Navigate the second time on authStateChanges(). I appreciate for the help you can provide. I believe it has to do with the Null check on newer versions as this issue didn't happen on sdk 2.7.0

CodePudding user response:

Split your file main.dart into two different files

Do not put any logic in this file main.dart

Split file is solution for your issue

main.dart

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
  final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      routes: {
        'home': (_) => HomeScreen(),
        
      },
      home: LoginScreen(),
    );
  }
}

login_screen.dart

import 'package:flutter/material.dart';

class LoginScreen extends StatefulWidget {
  const LoginScreen({Key? key}) : super(key: key);

  @override
  State<LoginScreen> createState() => _SplashScreenState();
}

class _SplashScreenState extends State<LoginScreen> {
  final Future<FirebaseApp> _initialization = Firebase.initializeApp();

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

  mainScreen() {
    return FutureBuilder(
      future: _initialization,
      builder: (context, snapshot) {
        if (snapshot.hasError) {
          return const ErrorPage(
            errorMessage: 'Unknown error',
          );
        }

        if (snapshot.connectionState == ConnectionState.done) {
          FirebaseAuth.instance.authStateChanges().listen((User? user) {
            if (user == null) {
              Navigator.of(context).pushReplacementNamed('login');
            } else {
              Navigator.of(context).pushReplacementNamed('home');
            }
          });
        }

        return const LoadingPage();
      },
    );
  }
}

CodePudding user response:

For some reason the context becomes null when authStateChanges() happens. Thanks to @Saitoh-Akira, I got the idea of using navigator Key and use it to navigate without the context. If I understand this correctly, the Navigator needs a state. Anyway, adding the navigator Key and use it worked good:

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:pollux_android/src/pages/error_page.dart';
import 'package:pollux_android/src/pages/loading_page.dart';
import 'package:pollux_android/src/routes/routes.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
  // final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
}

class _MyAppState extends State<MyApp> {
  final Future<FirebaseApp> _initialization = Firebase.initializeApp();
  final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      routes: polluxRoutes,
      navigatorKey: navigatorKey,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: mainScreen(),
    );
  }

  mainScreen() {
    return FutureBuilder(
      future: _initialization,
      builder: (context, snapshot) {
        if (snapshot.hasError) {
          return const ErrorPage(
            errorMessage: 'Some unknown error happened',
          );
        }

        if (snapshot.connectionState == ConnectionState.done) {
          FirebaseAuth.instance.authStateChanges().listen((User? user) {
            if (user == null) {
              navigatorKey.currentState?.pushNamedAndRemoveUntil('login', (route) => false);
            } else {
              navigatorKey.currentState?.pushNamedAndRemoveUntil('home', (route) => false);
            }
          });
        }

        return const LoadingPage();
      },
    );
  }
}

  • Related