The MaterialApp.Router widget is supposed to rebuild whenever the theme is changed but it is not. When I do a manual hot reload after tapping a color the theme changes. Any ideas?
I'm using the following package versions:
dependencies:
go_router: ^9.0.0
flutter_riverpod: ^2.3.6
riverpod_annotation: ^2.1.1
dev_dependencies:
build_runner: ^2.4.6
riverpod_generator: ^2.2.3
Here is my code:
main.dart
void main() {
runApp(
ProviderScope(
child: const MyApp(),
),
);
}
app.dart
class MyApp extends ConsumerWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp.router(
title: "MyApp",
routerConfig: goRouter,
locale: Locale("en"),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
theme: ref.watch(themeProvider).state,
);
}
}
theme_provider.dart
part 'theme_provider.g.dart';
@riverpod
ThemeState theme(ThemeRef ref) {
return ThemeState(themeRepository: ThemeRepository());
}
class ThemeState extends StateNotifier<ThemeData> {
IThemeRepository themeRepository;
ThemeState({required IThemeRepository this.themeRepository})
: super(AppTheme.gold.getThemeData) {
_getStoredTheme();
}
void setCurrentTheme(AppTheme value) {
state = value.getThemeData;
_storeTheme(value);
}
Future<void> _getStoredTheme() async {
String themeName = await themeRepository.GetTheme();
state = AppTheme.values.byName(themeName).getThemeData;
}
Future<bool> _storeTheme(AppTheme appTheme) async {
return await themeRepository.SetTheme(appTheme.name);
}
}
app_theme.dart
enum AppTheme {
gold,
green,
red,
black;
ThemeData get getThemeData => switch (this) {
AppTheme.gold => Themes.goldTheme,
AppTheme.green => Themes.greenTheme,
AppTheme.red => Themes.redTheme,
AppTheme.black => Themes.blackTheme,
};
}
themes.dart
class Themes {
static ThemeData get baseTheme => ThemeData(
useMaterial3: true,
brightness: Brightness.light,
);
static ThemeData get goldTheme => baseTheme.copyWith(
primaryColor: Color(0xffB58A35),
colorScheme: ColorScheme.fromSeed(seedColor: Color(0xffB58A35)),
);
static ThemeData get greenTheme => baseTheme.copyWith(
primaryColor: Color(0xff347743),
colorScheme: ColorScheme.fromSeed(seedColor: Color(0xff347743)),
);
static ThemeData get redTheme => baseTheme.copyWith(
primaryColor: Color(0xffD83731),
colorScheme: ColorScheme.fromSeed(seedColor: Color(0xffD83731)),
);
static ThemeData get blackTheme => baseTheme.copyWith(
primaryColor: Color(0xff313438),
colorScheme: ColorScheme.highContrastDark(
primary: Color(0xff313438),
secondary: Colors.white,
),
);
}
settings_page.dart
Row(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: [
GestureDetector(
child: Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color: AppTheme
.gold.getThemeData.primaryColor,
borderRadius:
BorderRadius.circular(4),
),
),
onTap: () {
ref
.read(themeProvider)
.setCurrentTheme(AppTheme.gold);
},
),
SizedBox(width: 4),
GestureDetector(
child: Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color: AppTheme
.green.getThemeData.primaryColor,
borderRadius:
BorderRadius.circular(4),
),
),
onTap: () {
ref
.read(themeProvider)
.setCurrentTheme(AppTheme.green);
},
),
SizedBox(width: 4),
GestureDetector(
child: Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color: AppTheme
.red.getThemeData.primaryColor,
borderRadius:
BorderRadius.circular(4),
),
),
onTap: () {
ref
.read(themeProvider)
.setCurrentTheme(AppTheme.red);
},
),
SizedBox(width: 4),
GestureDetector(
child: Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color: AppTheme
.black.getThemeData.primaryColor,
borderRadius:
BorderRadius.circular(4),
),
),
onTap: () {
ref
.read(themeProvider)
.setCurrentTheme(AppTheme.black);
},
),
],
);
You are using the code generator the wrong way, your
ThemeState
should be annotated with@riverpod
too. Your currentthemeProvider
is wrappingThemeState
with its own provider which means that it won't be notified of a change of state.Your code should be something like this:
theme_provider.dart
app.dart