25

Error: Runner[463:34314] flutter: LateInitializationError: Field 'name' has not been initialized.

I recently updated to using firebase core and nullsafety and made some changes to my code that I don't quite understand, I'm new to programming here. Any way, I've tried reading this similar thread here about it but I still don't quite grasp it. I understand that I am not using name properly in the initstate most likely but that is as much as I understand. Can someone please provide an example code of what's needed to solve for the error below?

2021-04-10 17:59:41.331476-0700 Runner[463:34314] flutter: LateInitializationError: Field 'name' has not been initialized.

class MyService extends StatefulWidget {
  @override
  _MyServiceState createState() => _MyServiceState();
}

class _MyServiceState extends State<MyService> {
  late String name, email;
  Widget currentWidget = BackgroundBetcher();

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    findNameAnEmail();
  }

  Future<Null> findNameAnEmail() async {
    await Firebase.initializeApp().then((value) async {
      FirebaseAuth.instance.authStateChanges().listen((event) {
        setState(() {
          name = event!.displayName!;
          email = event.email!;
        });
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: MyStyle().primaryColor,
      ),
      drawer: buildDrawer(),
      body: currentWidget,
    );
  }

  Drawer buildDrawer() {
    return Drawer(
      child: Stack(
        children: [
          Column(
            children: [
              buildUserAccountsDrawerHeader(),
              buildListTileShowCartoonList(),
              buildListTileInformation(),
            ],
          ),
          buildSignOut(),
        ],
      ),
    );
  }

  ListTile buildListTileShowCartoonList() {
    return ListTile(
      leading: Icon(
        Icons.face,
        size: 36,
      ),
      title: Text('Manual Location Update'),
      subtitle: Text('Send a single location update'),
      onTap: () {
        setState(() {
          currentWidget = PageWidget();
        });
        Navigator.pop(context);
      },
    );
  }

  ListTile buildListTileInformation() {
    return ListTile(
      leading: Icon(
        Icons.perm_device_info,
        size: 36,
      ),
      title: Text('Background Location Fetch Log'),
      subtitle: Text('History of recorded locations'),
      onTap: () {
        setState(() {
          currentWidget = BackgroundBetcher();
        });
        Navigator.pop(context);
      },
    );
  }

  UserAccountsDrawerHeader buildUserAccountsDrawerHeader() {
    return UserAccountsDrawerHeader(
      decoration: BoxDecoration(
        image: DecorationImage(
            image: AssetImage('images/wall.jpg'), fit: BoxFit.cover),
      ),
      accountName: MyStyle().titleH3(name),
      accountEmail: MyStyle().titleH3(email),
      currentAccountPicture: Image.asset('images/logo.png'),
    );
  }

  Column buildSignOut() {
    return Column(
      mainAxisAlignment: MainAxisAlignment.end,
      children: [
        ListTile(
          onTap: () async {
            await Firebase.initializeApp().then((value) async {
              await FirebaseAuth.instance.signOut().then((value) =>
                  Navigator.pushNamedAndRemoveUntil(
                      context, '/authen', (route) => false));
            });
          },
          tileColor: MyStyle().darkColor,
          leading: Icon(
            Icons.exit_to_app,
            color: Colors.white,
            size: 36,
          ),
          title: MyStyle().titleH2White('Sign Out'),
          subtitle: MyStyle().titleH3White('Sign Out & Go to Authen'),
        ),
      ],
    );
  }
}
giroprotagonist
  • 138
  • 1
  • 3
  • 15
  • 1
    I've answered your question, but on another note: `Future` is preferred over `Future` since the release of Dart 2. – hacker1024 Apr 11 '21 at 13:10

6 Answers6

50

You should be checking for nullable for the variable name. So, Use:

String? name;

instead of:

late String name

Late means,

I promise I will initialize this variable later

but this promise doesn't mean a thing when using that variable inside the build method.

Ojonugwa Jude Ochalifu
  • 26,627
  • 26
  • 120
  • 132
  • 1
    Android Studio suggests using late when updating to null safety, it took me awhile to figure out that the '?' was what was needed, thanks for this. – giroprotagonist Oct 21 '21 at 02:27
  • 14
    Not gonna lie, null safety has been a pain – Ojonugwa Jude Ochalifu Oct 21 '21 at 05:39
  • 1
    I am not sure how replacing late initialized variable with a nullable one solves the issue? This is mostly a problem with the subject calling something in the wrong order and the Flutter compiler is smart enough to figure that out. – sjsam Dec 08 '21 at 10:37
6

findNameAnEmail is an asynchronous method, so, while it's called in initState, Flutter does not wait for it to complete before build is called. This results in your late fields being accessed before they are set.

In order to wait for a Future to complete before building, consider using FutureBuilder.

hacker1024
  • 3,186
  • 1
  • 11
  • 31
  • 1
    Thanks for reading and answering, I now understand the purpose of FutureBuilder but not how to implement. Could you please provide an example of the changes I need to make? Thank you. – giroprotagonist Apr 11 '21 at 16:30
  • I would consider this as the correct answer. Upvoted! – filiphosko Mar 14 '23 at 17:41
3

For LateInitializationError, Simply use int? count; instead of late int count;

NirajPhutane
  • 1,586
  • 1
  • 12
  • 10
3

I had the same problem of lateInitializationError I find out to use ? to avoid it. if some one is facing this problem instead of late try ?.

For Example:

Gender? selectedGender;
Younas
  • 75
  • 1
  • 6
1

As i was facing the same problem i used the Future Builder the snapshot.data cant be null to handle this just use if block (snapshot.data==null) then return container with child cneter Text('Loading') until future completes screen will show loading and then will display dataSolution

-1

I'm very new to flutter, but this worked for me.

@override
void initState() {
    // TODO: implement initState
    super.initState();

    findNameAndEmail().whenComplete(() {
        setState(() {});
    });
}
Josef
  • 2,869
  • 2
  • 22
  • 23
Hlew
  • 7
  • 1
  • Not working for me Still getting error `LateInitializationError: Field '_cartFuture@52302676' has not been initialized.` – Prototype Aug 28 '21 at 09:16
  • 1
    I wouldn't recommend this method for a couple of reasons. First of all, it's not safe. There's no guarantee that the widget will still be mounted when `setState` is called, and if it's not, a runtime error will occur. Additionally, it's not optimised. Rather than rebuilding the entire widget, using something like `FutureBuilder` will only rebuilt the components that use the future. – hacker1024 Oct 24 '21 at 07:06