Search code examples
flutterdartsharedpreferencesflutter-sharedpreference

Shared Preferences key value not changing


I want to write code that directs the user to a welcome page if it's the first time the app is being run. After the user logs in, any subsequent launches of the app direct the user to log in, skipping the welcome page. It seems that when I try to set the value of my key upon logging in, it's not changing, because after logging in, closing the app and launching it again it's still going to the welcome page. How do I fix this? I'm not sure whether the issue is with the initialisation or the setting of the value upon login.

Here's the initialisation of my app:

import 'package:screens/welcomepages/signup_or_login.dart';
import 'package:screens/welcomepages/welcome.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:config/theme.dart';
import 'package:shared_preferences/shared_preferences.dart';

Future<SharedPreferences> _prefs = SharedPreferences.getInstance();

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
      statusBarColor: Colors.transparent,
      statusBarBrightness: Brightness.dark));
  runApp(MyApp(prefs: await _prefs));
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key, this.title, required this.prefs})
      : super(key: key);
  final String? title;
  final SharedPreferences prefs;

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

class _MyAppState extends State<MyApp> {
  late SharedPreferences prefs;

  @override
  void initState() {
    super.initState();
    initializePreference();
  }

  Future<void> initializePreference() async {
    prefs = await SharedPreferences.getInstance();
    setState(() {
      prefs.setBool("hasLoggedIn", false);
    });
  }

  @override
  Widget build(BuildContext context) {
    if (prefs.getBool("hasLoggedIn") == false) {
      return MaterialApp(
        theme: theme(),
        debugShowCheckedModeBanner: false,
        home: Welcome(prefs: prefs),
      );
    }
    return MaterialApp(
      theme: theme(),
      debugShowCheckedModeBanner: false,
      home: SignUpOrLogIn(prefs: prefs),
    );
  }
}

And here's the relevant parts of my log in page

import 'package:services/auth/auth_service.dart';
import 'package:widgets/text_fields_widgets/email_textfield.dart';
import 'package:widgets/text_fields_widgets/password_textfeild.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class Login extends StatefulWidget {
  const Login({Key? key, required this.prefs}) : super(key: key);
  final SharedPreferences prefs;

  @override
  _LoginState createState() => _LoginState(prefs);
}

class _LoginState extends State<Login> {
  late final SharedPreferences prefs;
  _LoginState(SharedPreferences prefs);

  Future<void> initializePreference() async {
    prefs = await SharedPreferences.getInstance();
  }

  @override
  void initState() {
    super.initState();
    initializePreference().whenComplete(() {
      setState(() {
        prefs.getBool("isFirstRun");
      });
    });
  }

 @override
  Widget build(BuildContext context) {
    Material btnLogin = loginBTN(context);
    return Scaffold(
      .....
      Padding(
        padding: const EdgeInsets.all(8.0),
        child: btnLogin,
      )
    }

  Material loginBTN(BuildContext context) {
    // ignore: unused_local_variable
    final btnLogin = Material(
      elevation: 5,
      borderRadius: BorderRadius.circular(30),
      color: Theme.of(context).primaryColor,
      child: MaterialButton(
        padding: const EdgeInsets.fromLTRB(20, 15, 20, 15),
        minWidth: MediaQuery.of(context).size.width,
        onPressed: () async {
          setState(() {
            prefs.setBool("hasLoggedIn", true);
          });
          setState(
            () => loadingAnimation = true,
          );
          await Future.delayed(const Duration(seconds: 1));
          setState(
            () => loadingAnimation = false,
          );
          await Authservice().logInMethod(
              emailController.text, passwordController.text, context, _formKey);
        },
        child: loadingAnimation
            ? const CircularProgressIndicator(
                color: Colors.white,
              )
            : const Text(
                "Log in",
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: 24, color: Colors.white),
              ),
      ),
    );
    return btnLogin;
  }
}

Sorry for how lengthy this is, tried to shorten it to only provide what's relevant.


Solution

  • Your are calling initializePreference() inside initState() and that function set hasLoggedIn to false. So even if you set it to true in your login page, when restarting the app it will be set again to false.