Themes are switched using RIverpod; ThemeMode is saved using Shared Preferences. They are working fine.But when I set the default values as follows, the default theme is shown for a moment at the beginning. That is ugly.
late ThemeMode _themeMode = ThemeMode.system;.
If I don't set the initial value, I get the following error, but the application runs fine without crashing.
late ThemeMode _themeMode;
LateInitialisationError: field '_themeMode@47036434' has not been initialised.
The whole code looks like this.
void main() async {
WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
await SharedPreferences.getInstance();
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends ConsumerWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Demo App',
theme: myLightTheme,
darkTheme: myDarkTheme,
themeMode: ref.watch(themeModeProvider).mode,
home: const HomeScreen(),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../utils/theme_mode.dart';
final themeModeProvider = ChangeNotifierProvider((ref) => ThemeModeNotifier());
class ThemeModeNotifier extends ChangeNotifier {
late ThemeMode _themeMode = ThemeMode.system;
ThemeModeNotifier() {
_init();
}
ThemeMode get mode => _themeMode;
void _init() async {
_themeMode = await loadThemeMode(); // get ThemeMode from shared preferences
notifyListeners();
}
void update(ThemeMode nextMode) async {
_themeMode = nextMode;
await saveThemeMode(nextMode); // save ThemeMode to shared preferences
notifyListeners();
}
}
I would like to somehow prevent this error from appearing. Please, I would appreciate it if you could help me.
I tryed to delete "late" and be nullable. But it didn't work.
Added theme_mode.dart
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
int modeToVal(ThemeMode mode) {
switch (mode) {
case ThemeMode.system:
return 1;
case ThemeMode.dark:
return 2;
case ThemeMode.light:
return 3;
default:
return 0;
}
}
ThemeMode valToMode(int val) {
switch (val) {
case 1:
return ThemeMode.system;
case 2:
return ThemeMode.dark;
case 3:
return ThemeMode.light;
default:
return ThemeMode.system;
}
}
Future<void> saveThemeMode(ThemeMode mode) async {
final pref = await SharedPreferences.getInstance();
pref.setInt('theme_mode', modeToVal(mode));
print('saveThemeMode: $mode');
}
Future<ThemeMode> loadThemeMode() async {
final pref = await SharedPreferences.getInstance();
final ret = valToMode(pref.getInt('theme_mode') ?? 0);
print('loadThemeMode: $ret');
return ret;
}
Here is the actual working code
import 'package:app_name/utils/theme_mode.dart' as theme_mode; // add
class StorageServiceImpl extends StorageService {
@override
Future<ThemeMode> loadThemeMode() => Future(() => theme_mode.loadThemeMode()); // update
@override
Future<void> saveThemeMode(ThemeMode mode) async {
theme_mode.saveThemeMode(mode); // add
}
}
Now the theme changes are perfect, no more momentary initial value display when loading, etc. Thank you so much, I really appreciate it.