Search code examples
fluttersharedpreferences

Flutter LocalStorage: LateInitializationError: Field 'localStorage' has not been initialized


I am new to Flutter, and I am stuck as I am using shared_preferences for auto login feature for an app. Here's the code for it.

When the exception was thrown, this was the stack:

#0 localStorage (package:ui_task/loginform.dart)

#1 MyApp.build (package:ui_task/main.dart:135:8)

#2 StatelessElement.build (package:flutter/src/widgets/framework.dart:4706:28)

#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4632:15)

#4 Element.rebuild (package:flutter/src/widgets/framework.dart:4322:5)

bool? isLoginDoneBefore;
void main() {
  runApp(MyApp());
}
// ignore: must_be_immutable
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  // late bool? isLoginDoneBefore = localStorage.getBool("isLoginSuccessful");
  @override

  void initState() {
    getData();
  }

  getData() async{
    SharedPreferences prefs = await SharedPreferences.getInstance();
    isLoginDoneBefore=prefs.getBool("isLoginSuccessful");
  }


  Widget build(BuildContext context) {
    // ignore: unnecessary_null_comparison
    if(localStorage==null || isLoginDoneBefore==null){
      return MaterialApp(
        title: 'Login Form',
        theme: ThemeData(
          primarySwatch: Colors.blueGrey,
        ),
        home: LoginFormWithAutoValidation(),
      );
    }
    else {
      return MaterialApp(
        title: 'Login Form',
        theme: ThemeData(
          primarySwatch: Colors.blueGrey,
        ),
        home: isLoginDoneBefore! ? afterLogin() : LoginFormWithAutoValidation(),
      );
    }
  }
}

UPDATE : Adding the topmost stack file. And here's the loginform.dart:


late SharedPreferences localStorage;

class LoginFormWithAutoValidation extends StatefulWidget {
  @override
  _LoginFormWithAutoValidationState createState() => _LoginFormWithAutoValidationState();

  // static Future init() async{
  //   localStorage = await SharedPreferences.getInstance();
  // }

}

class _LoginFormWithAutoValidationState extends State<LoginFormWithAutoValidation> {

  TextStyle style = TextStyle(fontFamily: 'Montserrat', fontSize: 20.0);

  TextEditingController _passwordController = new TextEditingController();
  TextEditingController _unameController = new TextEditingController();

  final _formKey = new GlobalKey<FormState>();
  late bool isLoginSuccessful;
  late String? _uname;
  late String? _password;
  bool _autoValidate = false;
  save() async{
    // await LoginFormWithAutoValidation.init();
    localStorage.setString('uname',_unameController.text.toString());
    localStorage.setString('password',_passwordController.text.toString());
    localStorage.setBool("isLoginSuccessful",true);
  }
  @override
  Widget build(BuildContext context) {

    return Scaffold(
      backgroundColor: Colors.blueGrey[900],
      body: Center(
        child: SingleChildScrollView(
          child: Padding(
            padding: const EdgeInsets.all(10.0),
            child: Column(
            . . . . .
            Material(
                   // login button
                            
                onPressed: () {
                    if (_formKey.currentState!.validate()) {
                        save();
                        Navigator.push(context,MaterialPageRoute(builder: (context) {
                              return afterLogin();}));
                    } else {
                            setState(() 
                             // validation error
                             _autoValidate = true;
                    });
              }


Solution

  • You are defining localStorage at the top of the loginform.dart file, but you are not initializing it with await SharedPreferences.getInstance(); that is why the error is thrown. Apart from that i would not recommend storing the password in cleartext in shared_preferences (if at all). It can easily be extracted. If you absolutely have to store it i would recommend: https://pub.dev/packages/flutter_secure_storage