Reputation: 611
I'm trying to implement dark and light themes in my Flutter app. To do this, I'm using a ViewModel approach to notify the whole application when the theme changes. When a user changes the theme, I'm saving it using shared_preferences. When the application starts again, I'm loading the saved theme from shared preferences:
main.dart
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<ThemeViewModel>(
builder: (context, themeViewModel, _) => MaterialApp(
theme: themeViewModel.getTheme(),
...
theme_view_model
class ThemeViewModel extends ChangeNotifier {
final darkTheme = ThemeData(...;
final lightTheme = ThemeData(...);
late ThemeData _themeData;
ThemeData getTheme() => _themeData;
ThemeViewModel() {
StorageManager.readData('themeMode').then((value) {
var themeMode = value ?? 'light';
if (themeMode == 'light') {
_themeData = lightTheme;
} else {
_themeData = darkTheme;
}
notifyListeners();
});
}
...
}
However, when I start the app, I get the error screen for a few seconds (probably before the theme data is loaded from the shared preferences):
How can this be solved? How could I display e.g. a loading spinner until the theme is loaded?
Upvotes: 1
Views: 836
Reputation: 9019
There are a few ways to solve it.
1-You can define an async initialize method for your ThemeViewModel
and wait for it in your main
method.
void main() async {
final viewModel = ThemeViewModel();
await viewModel.init();
...
}
class ThemeViewModel extends ChangeNotifier {
final darkTheme = ThemeData(...;
final lightTheme = ThemeData(...);
late ThemeData _themeData;
ThemeData getTheme() => _themeData;
Future init() async {
themeMode = await StorageManager.readData('themeMode') ?? 'light';
if (themeMode == 'light') {
_themeData = lightTheme;
} else {
_themeData = darkTheme;
}
}
}
2-You can provide a default theme to use when the _themeData is null
class ThemeViewModel extends ChangeNotifier {
final darkTheme = ThemeData(...;
final lightTheme = ThemeData(...);
ThemeData? _themeData;
ThemeData getTheme() => _themeData ?? lightTheme;
ThemeViewModel() {
StorageManager.readData('themeMode').then((value) {
var themeMode = value ?? 'light';
if (themeMode == 'light') {
_themeData = lightTheme;
} else {
_themeData = darkTheme;
}
notifyListeners();
});
}
...
}
Upvotes: 2