Flutter Firebase Authentication Example — showing a Home screen if logged in

This is a Flutter Firebase authentication example (using firebase_auth) were we are showing a Home screen (widget) if logged in and another screen (widget) if logged out. The relevant important dart code for actually listening if the user is logged in or not can be found at the highlighted lines. I am using firebase_auth: ^1.1.3 (which is very different from versions before 0.18.0). Read the comments and replace the Widgets to what you think should be for a logged in user and the logged out user. Right now we are simply just loading a Home widget, and in it, we will display Widget that is for the logged in user, or if logged out, we will display a Widget that is for the logged out user (in this case, AuthTypeSelector).

class AuthExampleApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'FileIdea Example App',
      theme: ThemeData.dark(),
      home: Scaffold(
        body: Home(),
      ),
    );
  }
}

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

  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  bool isloggedin = false;
  @override
  void initState() {
    super.initState();
    _auth.userChanges().listen((event) {
      updateStatus(event); //pass object
    });
  }

  updateStatus(event) {
    setState(() {
      isloggedin = event != null; //set variable true or false if logged in or not through set state 
      print("set!" + isloggedin.toString()); // print to log
    });
  }

  @override
  Widget build(BuildContext context) {
    if (isloggedin) {
      return Scaffold(
          appBar: AppBar(
            title: const Text('FileIdea Example App'),
          ),
          // Define your widget(s) that is for the logged in user
          body: Column(children: [
            Container(child: Text("Welcome you are logged in!")),
            TextButton(
                onPressed: () => {_auth.signOut()}, child: Text("Logout"))
          ]));
    } else {
      // Define your widget that is for the logged out user
      print("not logged in");
      return AuthTypeSelector();
    }
  }
}

My pubspec.yaml file:

environment:
  sdk: ">=2.7.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  firebase_auth: ^1.1.3
  cloud_firestore: ^2.0.0
  firebase_core: "^1.0.4"
  flutter_svg: ^0.22.0

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  google_sign_in: ^5.0.2
  flutter_signin_button: ^2.0.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  change_app_package_name: ^1.0.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

# The following section is specific to Flutter.
flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

Other helpful code can be found at FirebaseExtended with more Flutter Firebase authentication examples, with various logins and register sample.

method ‘[]’ can’t be unconditionally invoked because the receiver can be ‘null’ with Firestore

If you are working with null safety in Dart and Flutter then I recommend checking this documentation out which explains various small fixes if you have problems working with null values and null safety. Usually you can just simply use the exclamation mark just before a property to check any other value if it also can be null like this:

int f(String? x) { return x!.length; }

But in one situation I couldn’t simply just add the exclamation mark to my property when working with Firestore inside a map function when looping through the Snapshot document Data(). The error I got (see image below) was:

Error: The method ‘[]’ can’t be unconditionally invoked because the receiver can be ‘null’.
Try making the call conditional (using ‘?.’) or adding a null check to the target (‘!’).dart unchecked_use_of_nullable_value

The solution I searched for at the linked page didn’t solve my issue, so what I ended up doing was casting the object type. Let’s say you have a map function for your Firestore CollectionReference like this:

        final mySnapStream = messagesCollection
        .orderBy('date', descending: true)
        .limit(100)
        .snapshots()
        .map((obj) => obj.docs
            .map((e) => new MyItem(
                e.data()['myFieldOne'],
                e.data()['myFieldThree'],
                e.data()['myFieldFour']))
            .toList());
method '[]' can't be unconditionally invoked because the receiver can be 'null'

Then you can simply cast these values with dynamic like so:

      final mySnapStream = messagesCollection
        .orderBy('date', descending: true)
        .limit(100)
        .snapshots()
        .map((obj) => obj.docs
            .map((e) => new MyItem(
                (e.data() as dynamic)['myFieldOne'],
                (e.data() as dynamic)['myFieldThree'],
                (e.data() as dynamic)['myFieldFour']))
            .toList());
method '[]' can't be unconditionally invoked because the receiver can be 'null' fixed

This way we don’t have any errors any longer. The MyItem class was not defined here so please ignore that. Obivously there are probably better ways to go about this, but this is one way.