I am using Provider to manage the Dark/Light theme across a Flutter mobile application and I need to store the theme setting in Shared Preferences as a boolean currently the theme setting is controlled via a Switch.
I couldn't figure out how to do it and couldn't make my way around Shared Prefs.
Below is my attempt at implementing said feature but couldn't make it work.
Q: How to implement Shared Prefs and store the theme data inside?
Switch button widget:
class ThemeToggle extends StatelessWidget {
setThemeModeSP(bool isDark) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool('isDarkEnabled', isDark);
}
isPresentSP(String prefKey) async {
SharedPreferences sp = await SharedPreferences.getInstance();
if (sp.containsKey(prefKey)) {
return true;
} else {
return false;
}
}
removeThemeModeSP() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.remove('isDarkEnabled');
}
@override
Widget build(BuildContext context) {
final themeProvider = Provider.of<ThemeProvider>(context);
return Switch.adaptive(
value: themeProvider.isDarkMode,
onChanged: (value) {
final provider = Provider.of<ThemeProvider>(context, listen: false);
provider.toggleTheme(value);
setThemeModeSP(value);
});
}
}
Theme provider class
class ThemeProvider extends ChangeNotifier {
ThemeMode themeMode = ThemeMode.light;
bool get isDarkMode => themeMode == ThemeMode.dark;
void toggleTheme(bool isOn) {
themeMode = isOn ? ThemeMode.dark : ThemeMode.light;
notifyListeners();
}
}
UPDATE: I MANAGED TO STORE A DARK MODE BOOLEAN IN SHARED PREFERENCES BUT WHEN I RETRIEVE IT THE THEME DOES NOT CHANGE
I tested and found the the boolean value is stored and retrieved successfully the only problem that remains is that the theme goes back to default when app is restarted
Here are the changes I made:
Switch button widget:
class ThemeToggle extends StatelessWidget {
@override
Widget build(BuildContext context) {
final themeProvider = Provider.of<ThemeProvider>(context);
return Switch.adaptive(
value: themeProvider.isDarkMode,
onChanged: (value) {
final provider = Provider.of<ThemeProvider>(context, listen: false);
provider.toggleTheme(value);
mSharedPrefs.setBool('myThemeMode', value);
});
}
}
Theme provider class
isPresentSP(String prefKey) async {
SharedPreferences sp = await SharedPreferences.getInstance();
if (sp.containsKey(prefKey)) {
return true;
} else {
return false;
}
}
Future<bool> fetchThemeSettingsFromSP() async {
SharedPreferences mSharedPrefs = await SharedPreferences.getInstance();
try {
if (isPresentSP('myThemeMode') == false) {
return false;
} else {
var spr = mSharedPrefs.getBool('myThemeMode');
if (spr != null) {
if (spr) {
return true;
} else if (!spr) {
return false;
}
} else if (spr == null) {
return false;
}
}
return false;
} catch (e) {
print('fetch theme from SP err: ' + e.toString());
return false;
}
}
themeModeSettings() {
fetchThemeSettingsFromSP().then((val) {
if (val == null) {
return false;
} else {
return val;
}
});
}
class ThemeProvider extends ChangeNotifier {
ThemeMode themeMode = ThemeMode.light;
bool get isDarkMode => themeModeSettings() ?? themeMode == ThemeMode.dark;
void toggleTheme(bool isOn) {
themeMode = isOn ? ThemeMode.dark : ThemeMode.light;
notifyListeners();
}
}