Dark/light theme preferences do not save in the system. Flutter

Viewed 106

I am trying to add dark/light/custom theme modes in my Flutter application. I've used this tutorial, but my theme preferences do not save and do not apply after the application is restarted. I am using the shared_preferences library in my project, which you can access here

I've tried importing theme_manager.dart and other files as a packages and my storage_manager file looks like this now:

import 'package:shared_preferences/shared_preferences.dart';
import 'package:calculator/main.dart';
import 'package:calculator/theme_manager.dart';
import 'package:calculator/settings.dart';

class StorageManager {
  static void saveData(String key, dynamic value) async {
    final prefs = await SharedPreferences.getInstance();
    print(value);
    if (value is int) {
      prefs.setInt(key, value);
    } else if (value is String) {
      prefs.setString(key, value);
    } else if (value is bool) {
      prefs.setBool(key, value);
    } else {
      print("Invalid Type");
    }
  }

  static Future<dynamic> readData(String key) async {
    final prefs = await SharedPreferences.getInstance();
    dynamic obj = prefs.get(key);
    return obj;
  }

  static Future<bool> deleteData(String key) async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.remove(key);
  }
}

And function in theme_manager.dart, that should change theme (at the app start), looks like this:

late ThemeData _themeData;
var _buttonsData;

ThemeData getTheme() => _themeData;
getButtons() => _buttonsData;

ThemeNotifier() {
  StorageManager.readData('themeMode').then((value) {
    var themeMode = value ?? 'light';
    if (themeMode == 'light') {
        _themeData = lightTheme;
    } else if (themeMode == 'dark') {
        _themeData = darkTheme;
    } else {
        _themeData = customTheme;
    }
      notifyListeners();
    });
  StorageManager.readData('buttonsMode').then((value) {
    var buttonsMode = value ?? 'circle';
    if (buttonsMode == 'circle') {
        _buttonsData = circledButtons;
    } else if (buttonsMode == 'rounded') {
        _buttonsData = roundedButtons;
    } else if (buttonsMode == 'box') {
        _buttonsData = boxButtons;
    }
      notifyListeners();
  });
}

In the original example - there is no late argument before ThemeData _themeData;, but without it, my whole code does not work. Can this be a problem? Any help would be much appreciated!

1 Answers

Your initialization process isn't working because you are not waiting for it. So you never get the saved theme from shared preferences. You can change your ThemeNotifier to something like that:

  ThemeNotifier();

  Future<void> init() async {
      final themeMode = await StorageManager.readData('themeMode') ?? 'light';
      final buttonsMode =
          await StorageManager.readData('buttonsMode') ?? 'circle';

      if (themeMode == 'light') {
        _themeData = lightTheme;
      } else if (themeMode == 'dark') {
        _themeData = darkTheme;
      } else {
        _themeData = customTheme;
      }

      if (buttonsMode == 'circle') {
        _buttonsData = circledButtons;
      } else if (buttonsMode == 'rounded') {
        _buttonsData = roundedButtons;
      } else if (buttonsMode == 'box') {
        _buttonsData = boxButtons;
      }

      notifyListeners();
  }

Then in your main method you should await the init method

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations(
      [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);

  final themeNotifier = ThemeNotifier();
  await themeNotifier.init();
  return runApp(ChangeNotifierProvider<ThemeNotifier>.value(
    value: themeNotifier,
    child: const MyApp(),
  ));
}

This way ThemeNotifier will be initialized with your saved value

Related