In my flutter project, I selected riverpod_hook
for DI.
In order to change the language setting of the application according to the language setting of the mobile device, I wrote the code as follows.
// app.dart
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
class Application extends ConsumerWidget {
const Application({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp(
theme: defaultTheme,
localizationsDelegates: Resource.localizationsDelegates,
supportedLocales: Resource.supportedLocales,
localeResolutionCallback: (Locale? locale, Iterable<Locale> supportedLocales) {
if (supportedLocales.any((element) => locale?.languageCode.contains(element.toString()) == true)) {
ref.watch(localeCodeProvider.notifier).state = locale!.languageCode;
return locale;
}
return const Locale('ko', '');
},
routes: {
homePageRoutes: (_) => const HomePage(),
detailPageRoutes: (_) => const DetailPage(),
},
);
}
}
import 'package:hooks_riverpod/hooks_riverpod.dart';
final localeCodeProvider = StateProvider<String>((ref) => 'en');
When I run this code, this error was occurred.
E/flutter ( 3747): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: Tried to modify a provider while the widget tree was building.
E/flutter ( 3747): If you are encountering this error, chances are you tried to modify a provider
E/flutter ( 3747): in a widget life-cycle, such as but not limited to:
E/flutter ( 3747): - build
E/flutter ( 3747): - initState
E/flutter ( 3747): - dispose
E/flutter ( 3747): - didUpdateWidget
E/flutter ( 3747): - didChangeDepedencies
E/flutter ( 3747):
E/flutter ( 3747): Modifying a provider inside those life-cycles is not allowed, as it could
E/flutter ( 3747): lead to an inconsistent UI state. For example, two widgets could listen to the
E/flutter ( 3747): same provider, but incorrectly receive different states.
E/flutter ( 3747):
E/flutter ( 3747):
E/flutter ( 3747): To fix this problem, you have one of two solutions:
E/flutter ( 3747): - (preferred) Move the logic for modifying your provider outside of a widget
E/flutter ( 3747): life-cycle. For example, maybe you could update your provider inside a button's
E/flutter ( 3747): onPressed instead.
E/flutter ( 3747):
E/flutter ( 3747): - Delay your modification, such as by encasuplating the modification
E/flutter ( 3747): in a `Future(() {...})`.
E/flutter ( 3747): This will perform your upddate after the widget tree is done building.
I can see from the error message that the error occurred because the provider watch
was used inside the build function.
However, I unwillingly need to utilize that localeResolutionCallback
attribute because I want to set the language setting value of the mobile device and set the language across the application.
In this situation, could I get an appropriate solution on how to use the provider
?
CodePudding user response:
Try if calling WidgetsBinding.instance.addPostFrameCallback would work, somethign like this:
if (supportedLocales.any((element) => locale?.languageCode.contains(element.toString()) == true)) {
WidgetsBinding.instance.addPostFrameCallback((_) {
ref.watch(localeCodeProvider.notifier).state = locale!.languageCode;
});
return locale;
}
```
What it does - it allows your build to complete; and then changes the provider - which will most likely call another build.