I am using Hive with app_profile data model to store the app settings in local DB, and using riverpod to call HivedataStore (dependency injection).
The problem is that when I update the hive box of the local type, the app needs to be restarted to take effect, but if I update the Theme to Dark it work as it supposed to.
Here is my code:
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// await AppAssets.preloadSVGs();
final dataStore = HiveDataStore();
await dataStore.init();
await dataStore.createDefaultProfile(
appProfile: AppProfile(
onBoardingCompleted: false,
locale: 'en',
themeMode: ThemeModeCustomized.light,
));
runApp(ProviderScope(overrides: [
hiveDataStoreProvider.overrideWithValue(dataStore),
], child: const MyApp()));
}
hive_data_store.dart
class HiveDataStore {
static const profileBoxName = 'appProfile';
static const themeColor = 'themeColor';
Future<void> init() async {
await Hive.initFlutter();
Hive.registerAdapter<AppProfile>(AppProfileAdapter());
Hive.registerAdapter(ThemeModeCustomizedAdapter());
await Hive.openBox<AppProfile>(profileBoxName);
}
Future<void> createDefaultProfile({
required AppProfile appProfile,
}) async {
final box = Hive.box<AppProfile>(profileBoxName);
if (box.isEmpty) {
await box.put('0', appProfile);
} else {
print('box already have these Values : ${box.get(0)?.locale}');
}
}
Future<void> updateBox({
bool? onBoardingCompleted,
String? locale,
ThemeModeCustomized? themeMode,
}) async {
final box = Hive.box<AppProfile>(profileBoxName);
final userProfile = box.get('0');
final newProfile = userProfile!.copyWith(
onBoardingCompleted: onBoardingCompleted,
locale: locale,
themeMode: themeMode);
await box.put('0', newProfile);
}
AppProfile? appProfile() {
final box = Hive.box<AppProfile>(profileBoxName);
return box.get(0);
}
ValueListenable<Box<AppProfile>> appProfileListenable() {
return Hive.box<AppProfile>(profileBoxName).listenable();
}
}
final hiveDataStoreProvider = Provider<HiveDataStore>((ref) {
throw UnimplementedError();
});
myapp.dart
class MyApp extends ConsumerWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final provider = ref.watch(hiveDataStoreProvider);
return ValueListenableBuilder(
valueListenable: provider.appProfileListenable(),
builder: (context, Box<AppProfile> box, __) {
print('myapp rebuilds listenablebuilder');
final appProfile = box.get('0');
return MaterialApp(
debugShowCheckedModeBanner: false,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppAssets.getLocals(appProfile!),
onGenerateTitle: (context) {
var t = AppLocalizations.of(context);
return t!.appTitle;
},
themeMode: AppAssets.themeModeGeter(appProfile),
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
initialRoute: '/',
routes: {
'/': (context) {
return const HomePage();
}
},
);
});
}
}
homepage.dart
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
print('homepage rebuils');
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context)!.appTitle),
),
body: Center(
child: Consumer(builder: (context, WidgetRef ref, __) {
return Column(
children: [
TextButton(
onPressed: () {
ref.read(hiveDataStoreProvider).updateBox(
locale: 'ar', themeMode: ThemeModeCustomized.dark
);
},
child: const Text('العربية')),
TextButton(
onPressed: () {
ref.read(hiveDataStoreProvider).updateBox(
locale: 'en', themeMode: ThemeModeCustomized.light
);
},
child: const Text('English')),
],
);
}),
),
);
}
}
I think something need to be Changed in MyApp class, I use ValueListenableBuilder
because I've seen in it in the Hive official package page.
Why the app need to be restarted to take effect for the locales? Unlike the app Theme which works perfectly.
Here my app_assets.dart code (just extra info):
class AppAssets {
static List<Locale> getLocals(AppProfile appProfile) {
switch (appProfile.locale) {
case 'ar':
return [const Locale('ar', '')];
case 'en':
return [const Locale('en', '')];
case '':
return AppLocalizations.supportedLocales;
default:
return AppLocalizations.supportedLocales;
}
}
static ThemeMode themeModeGeter(AppProfile? appProfile) {
switch (appProfile?.themeMode.name) {
case 'dark':
{
return ThemeMode.dark;
}
case 'light':
{
return ThemeMode.light;
}
case 'system':
{
return ThemeMode.system;
}
default:
ThemeMode.system;
}
return ThemeMode.system;
}
}
my mistake is that I was updating supportedLocales
without updating locale
in the MaterialApp
Widget , I will keep the question though it might have a hint for others ..
supportedLocales: AppAssets.getLocals(appProfile),
locale: Locale('$appProfile.locale',''),