How do I set the theme of my app based on what's stored in shared_preferences
if all calls to shared_preferences
are async?
For example, I have a ThemeService
which looks up the set theme from shared_preferences
and returns it, this works for things like toggling it in the UI, but how do I load this at startup?
class ThemeService {
static String key = "isDark";
/// Return the ThemeData based on what is persisted.
Future<ThemeData> getTheme() async {
final prefs = await SharedPreferences.getInstance();
final isDarkMode = prefs.getBool(key) ?? false;
if (isDarkMode) {
return ThemeDark().theme;
} else {
return ThemeLight().theme;
}
}
/// Toggle the theme between light/dark and persist the chosen value.
Future<void> toggleTheme() async {
final prefs = await SharedPreferences.getInstance();
final isDarkMode = prefs.getBool(key) ?? false;
if (isDarkMode) {
Get.changeTheme(ThemeLight().theme);
await prefs.setBool(key, false);
} else {
Get.changeTheme(ThemeDark().theme);
await prefs.setBool(key, true);
}
}
}
And I want to be able to use it as such:
class App extends StatelessWidget {
final ThemeService themeService = Get.find<ThemeService>();
@override
Widget build(BuildContext context) {
return GetMaterialApp(
debugShowCheckedModeBanner: false,
initialBinding: InitialBinding(),
initialRoute: initialRoute(),
theme: themeService.getTheme(), // Its a future, so can't do this...
getPages: AppPages.routes);
}
}
New to flutter so have I just missed a concept or a pattern here? Is there some way I should be accessing the preferences as to not need async/await
?
As suggested in the comments, the solution is to wrap the GetMaterialApp
in a FutureBuilder
@override
Widget build(BuildContext context) {
return FutureBuilder<ThemeData>(
future: ThemeService().getTheme(),
builder: (BuildContext context, AsyncSnapshot<ThemeData> snapshot) {
return GetMaterialApp(
debugShowCheckedModeBanner: false,
initialBinding: InitialBinding(),
initialRoute: initialRoute(),
theme: snapshot.data,
darkTheme: darkTheme,
getPages: AppPages.routes);
});
}