skip to Main Content

I’ve build an android app, and I want when I open the application again it come to last value and state that I did before. This error is coming after I run the application. Can someone please provide an example code of what’s needed to solve for the error below?

Exception has occurred. LateError (LateInitializationError: Field ‘prefs’ has not been initialized.)

And this is my code:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(const MyApp());
}

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  var dataAddress;
  final _usernameController = TextEditingController();
  final _passwordController = TextEditingController();
  bool isPressed = true;
  var state = FlutterVpnState.disconnected;
  CharonErrorState? charonState = CharonErrorState.NO_ERROR;
  late SharedPreferences prefs;

  @override
  void initState() {
    super.initState();
    initSharedPreferences();
    FlutterVpn.prepare();
    FlutterVpn.onStateChanged.listen((s) => setState(() => state = s));
    SharedPreferences.getInstance().then((value) => prefs = value);
  }

  void initSharedPreferences() async {
    prefs = await SharedPreferences.getInstance();
    String? address = prefs.getString('address');
    String? username = prefs.getString('username');
    String? password = prefs.getString('password');
    dataAddress = address ?? '';
    _usernameController.text = username ?? '';
    _passwordController.text = password ?? '';
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: SafeArea(
          child: Scaffold(
            body: Stack(
              fit: StackFit.expand,
              children: <Widget>[
                ListView(
                  children: <Widget>[
                    StreamBuilder<QuerySnapshot>(
                      stream: FirebaseFirestore.instance.collection('servers').snapshots(includeMetadataChanges: true),
                      builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
                        if (snapshot.hasError) {
                          return Text('Something went wrong');
                        }
                        return DropdownSearch<String>(
                              dropdownDecoratorProps: DropDownDecoratorProps(
                                dropdownSearchDecoration: InputDecoration(
                                  labelText: "Server",
                                ),
                              ),
                              dropdownBuilder: ((context, selectedItem) {
                                return Text(
                                  selectedItem ?? ""
                                );
                              }),
                              items: snapshot.data!.docs.map((DocumentSnapshot document) {
                                    Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
                                    return data["address"];
                                  })
                                  .toList().cast<String>(),
                              onChanged: (data) {
                                setState(() {
                                  dataAddress = data;  
                                });
                              },
                              selectedItem: dataAddress,
                            );
                      },
                    ),

                    TextFormField(
                      controller: _usernameController,
                      decoration: InputDecoration(
                        labelText: 'Username',
                      ),
                    ),

                    TextFormField(
                      controller: _passwordController,
                      decoration: InputDecoration(
                        labelText: 'Password'
                      ),
                    ),

                      IconButton(
                        onPressed: () async {
                          if (state == FlutterVpnState.disconnected) {
                            setState(() {
                              isPressed = true;
                            });
                            try {
                              await FlutterVpn.connectIkev2EAP(
                                server: dataAddress,
                                username: _usernameController.text,
                                password: _passwordController.text,
                              );
                              setState(() {
                                isPressed = false;
                              });
                            } catch (e) {
                              setState(() {
                                isPressed = false;
                              });
                            }
                          } else {
                            FlutterVpn.disconnect();
                            setState(() {
                              isPressed = true;
                            });
                          }   
                        },
                        icon: state == FlutterVpnState.connecting || state == FlutterVpnState.disconnecting
                          ? LoadingAnimationWidget.inkDrop(
                            color: Colors.white,
                            size: 100
                          )
                          : state == FlutterVpnState.disconnected
                            ? Image.asset('assets/images/power-on.png')
                            : Image.asset('assets/images/power-off.png')
                      ),      
                    ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Edit:
I try two solution above, but after I close and I open the application again, it’s not come to last value and state.

enter image description here

2

Answers


  1. As you are using prefs only at the function initSharedPreferences. make it as a local variable

      void initSharedPreferences() async {
        final prefs = await SharedPreferences.getInstance();
        String? address = prefs.getString('address');
        String? username = prefs.getString('username');
        String? password = prefs.getString('password');
        dataAddress = address ?? '';
        _usernameController.text = username ?? '';
        _passwordController.text = password ?? '';
      }
    

    remove following two lines.

    late SharedPreferences prefs;
    
    SharedPreferences.getInstance().then((value) => prefs = value);
    

    I hope this helps.

    Login or Signup to reply.
  2. Reason:
    This is happening because your async function initSharedPreferences()is not awaited before using it in SharedPreferences.getInstance().then((value) => prefs = value);

    late SharedPreferences prefs;
    
      @override
      void initState() {
        super.initState();
        initSharedPreferences();  // 👈 await is not used , so the async function might be still running in the background where prefs is still not initialized.
        FlutterVpn.prepare();
        FlutterVpn.onStateChanged.listen((s) => setState(() => state = s));
        SharedPreferences.getInstance().then((value) => prefs = value); // You are not sure if the pref is initialized but you are using it anyways
      }
    
      void initSharedPreferences() async {
        prefs = await SharedPreferences.getInstance();
        String? address = prefs.getString('address');
        String? username = prefs.getString('username');
        String? password = prefs.getString('password');
        dataAddress = address ?? '';
        _usernameController.text = username ?? '';
        _passwordController.text = password ?? '';
      }
    

    Solution:

    1. remove the SharedPreferences.getInstance().then((value) => prefs = value); from initState() because you can’t await initSharedPreferences() function as it is initState(). And place it inside initSharedPreferences() function.
    late SharedPreferences prefs;
    
      @override
      void initState() {
        super.initState();
        initSharedPreferences(); 
        FlutterVpn.prepare();
        FlutterVpn.onStateChanged.listen((s) => setState(() => state = s));
       // SharedPreferences.getInstance().then((value) => prefs = value); // 👈 comment out
      }
    
      void initSharedPreferences() async {
        prefs = await SharedPreferences.getInstance();
        String? address = prefs.getString('address');
        String? username = prefs.getString('username');
        String? password = prefs.getString('password');
        dataAddress = address ?? '';
        _usernameController.text = username ?? '';
        _passwordController.text = password ?? '';
         SharedPreferences.getInstance().then((value) => prefs = value); 👈 add it here
      }
    
    1. You can even locally use prefs variable in the initSharedPreferences() function, and avoid defined it outside the function.
    // late SharedPreferences prefs;👈 remove this line
    
      @override
      void initState() {
        super.initState();
        initSharedPreferences(); 
        FlutterVpn.prepare();
        FlutterVpn.onStateChanged.listen((s) => setState(() => state = s));
       // SharedPreferences.getInstance().then((value) => prefs = value);👈 remove this line
      }
    
      void initSharedPreferences() async {
        SharedPreferences prefs = await SharedPreferences.getInstance(); // 👈 create variable locally
        String? address = prefs.getString('address');
        String? username = prefs.getString('username');
        String? password = prefs.getString('password');
        dataAddress = address ?? '';
        _usernameController.text = username ?? '';
        _passwordController.text = password ?? '';
      }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search