Home > database >  LateInitializationError: Field 'displayName' has not been initialized in Flutter's Sh
LateInitializationError: Field 'displayName' has not been initialized in Flutter's Sh

Time:12-23

I am creating an Flutter application in which i need to store the user information and for some extent i am able to achieve it with Shared Prefrence.

i am storing the data at login screen as follows:

    var displayName=jsondata["username"];
    SharedPreferences prefs=await SharedPreferences.getInstance();
    prefs.setString('displayName', displayName);

and on my drawerScreen i am getting the same data as follows:

 late String displayName;
 initState() {
  getData();
  super.initState();
 }
 getData() async{
  SharedPreferences prefs = await SharedPreferences.getInstance();
  displayName=prefs.getString('displayName')!;
 }

but whenever i click on drawer button there is an error as shown:

LateInitializationError: Field 'displayName' has not been initialized.

but when i hot reload my app while drawer is opened there is no error when i go to other screen and get back to drawer the LateInitialization errro arises,

i dont know what causing this error

here is the How error arises

and this is the other screen where i am shifting from drawer:

 late String displayName;

getData() async {
   SharedPreferences prefs = await SharedPreferences.getInstance();
  displayName=prefs.getString('displayName')!;
  print(displayName);
  }  

initState() {
   getData();
   super.initState();
 }

     @override
    Widget build(BuildContext context) {
    return Scaffold(
    backgroundColor: Theme.of(context).backgroundColor,
     key: _scaffoldKey,
     drawer: SizedBox(
       width: MediaQuery.of(context).size.width * 0.75 < 400 ? 
     MediaQuery.of(context).size.width * 0.75 : 350,
       child: Drawer(
       child: AppDrawer(
        selectItemName: 'Home',
      ),
    ),
  ),
  appBar: AppBar(
    backgroundColor: Theme.of(context).scaffoldBackgroundColor,
    automaticallyImplyLeading: false,
    title: Row(
      children: <Widget>[
        SizedBox(
          height: AppBar().preferredSize.height,
          width: AppBar().preferredSize.height   40,
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Container(
              alignment: Alignment.centerLeft,
              child: GestureDetector(
                onTap: () {
                  _scaffoldKey.currentState!.openDrawer();
                },
                child: Icon(
                  Icons.dehaze,
                  color: Theme.of(context).textTheme.headline6!.color,
                ),
              ),
            ),
          ),
        ),

      ],
    ),
  ),

can someone suggest me a better way of doing it . Thanks in advance <3

CodePudding user response:

Your problem is that initState is not async (and it can't be async), so your getData will likely (or surely) be completed later than the build method is called. Since you set displayName in getData, and you marked it as late, you will get this error. That's why it is working after hot reload, because at that time displayName is already initalized.

One possible solution is to call SharedPreferences.getInstance() (this is why your getData needs to be async) somewhere earlier in your application, for example in main() async function, store the result of getInstance using a ChangeNotifierProvider (or any other way that allows you to use this value in this widget), and use its value in getData. This way getData does not need to be async, and displayName will be initalized before build method is called. This can be useful if you use SharedPreferences in more than one place, because you don't have to await the result of getInstance each time.

Another approach is not declaring displayName as late, but allow it to be null, and then in the build method you can use a FutureBuilder which completes upon getData is executed, and the building of Scaffold will only be started after this future completes. In this case you can display a progress indicator while the future is not completed.

CodePudding user response:

I forgot to to add setState();

late String displayName;
initState() {
getData();
super.initState();
 }
 Future getData() async{
 SharedPreferences prefs = await SharedPreferences.getInstance();
 setState(() {
  displayName=prefs.getString('displayName')!;
  });

}
  • Related