Setting theme based on SharedPreference data

159

I suggest loading the preferences before the app is built and shown to the user:

Future<void> main() async {
  ...
  final preferences = await SharedPreferences.getInstance();

  runApp(MainApp(
    preferences: preferences,
  ));
}

In your case, you could pass the theme value to MyApp widget.

Share:
159
J0nathan Lam
Author by

J0nathan Lam

Updated on January 01, 2023

Comments

  • J0nathan Lam
    J0nathan Lam over 1 year

    My goal for this flutter app is to change the theme (Dark, Light, System) based on the stored Shared Preferences data. I used Provider so that every time the user changes the theme, the entire app will update based on the selected theme. The issue is when the user first starts up the app, it finishes building before we can get the value of the theme from Shared Preference. Therefore we are getting a null value for the theme when the app initially loads. My code only works if the user is updating the theme value after the app finishes loading on startup.

      void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      runApp(ChangeNotifierProvider<PreferencesProvider>(
          create: (context) {
            return PreferencesProvider();
          },
          child: MyApp()));
    }
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
    
        print(SettingsSharedPreferences.getThemeString());
        return ChangeNotifierProvider<HabitProvider>(
          create: (context) {
            return HabitProvider();
          },
          child: MaterialApp(
            darkTheme: ThemeData(brightness: Brightness.dark),
            themeMode: context.watch<PreferencesProvider>().theme == "System"
                ? ThemeMode.system
                : context.watch<PreferencesProvider>().theme == "Dark"
                    ? ThemeMode.dark
                    : context.watch<PreferencesProvider>().theme == "Light"
                        ? ThemeMode.light
                        : ThemeMode.system,
            home: MyHomePage(title: 'My App'),
          ),
        );
      }
    }
    

    This is the Provider class. Note that the variable theme is getting its data from the stored Shared Preferences data.

    class PreferencesProvider extends ChangeNotifier {
      String? theme =  SettingsSharedPreferences.getThemeString();
    ....
    }
    

    Below is the Shared Preference code where we get the value of theme from:

    class SettingsSharedPreferences {
      static const _keytheme = "theme";
      static String _defaultTheme = "System";
    
      static setTheme(String theme) async {
        await sharedPreferences.setString(_keytheme, theme);
      }
    
      static Future<String?> getTheme() async {
        final sharedPreferences = await SharedPreferences.getInstance();
        if (sharedPreferences.getString(_keytheme) == null) {
          await setTheme(_defaultTheme);
        }
        return sharedPreferences.getString(_keytheme);
      }
    
      static String? getThemeString() {
        print("getThemeString");
        String? theme;
        getTheme().then((val) {
          theme = val;
        });
        return theme;
      }
    }