Persisting State¶
NeatHydratedNotifier adds automatic persistence to your notifiers. It saves the state to disk whenever it changes and restores it when the notifier is initialized.
Usage¶
- Initialize Storage: Call
NeatHydratedStorage.initialize()beforerunApp. - Mix in
NeatHydratedNotifier: Add the mixin to your notifier. - Implement
id,fromJson, andtoJson: These are required for identification and serialization. - Call
hydrate(): Call this in the constructor to load the saved state.
class SettingsNotifier extends NeatNotifier<ThemeMode, void> with NeatHydratedNotifier<ThemeMode, void> {
SettingsNotifier() : super(ThemeMode.system) {
hydrate();
}
@override
String get id => 'settings_persistence';
@override
ThemeMode? fromJson(Map<String, dynamic> json) => ThemeMode.values[json['theme'] as int];
@override
Map<String, dynamic> toJson(ThemeMode state) => {'theme': state.index};
}
Example¶
import 'package:flutter/material.dart';
import 'package:neat_state/neat_state.dart';
class SettingsNotifier extends NeatNotifier<ThemeMode, void>
with NeatHydratedNotifier<ThemeMode, void> {
SettingsNotifier() : super(ThemeMode.system) {
hydrate();
}
@override
String get id => 'settings';
void toggle() =>
value = value == ThemeMode.light ? ThemeMode.dark : ThemeMode.light;
@override
ThemeMode? fromJson(Map<String, dynamic> json) =>
ThemeMode.values[json['theme'] as int];
@override
Map<String, dynamic> toJson(ThemeMode state) => {'theme': state.index};
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await NeatHydratedStorage.initialize(); // Uses default Hive storage
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return NeatState(
create: (_) => SettingsNotifier(),
builder: (context, mode, _) {
return MaterialApp(
themeMode: mode,
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
home: Scaffold(
appBar: AppBar(title: const Text('Hydrated State Demo')),
body: Center(child: Text('Current Mode: $mode')),
floatingActionButton: FloatingActionButton(
onPressed: () => context.read<SettingsNotifier>().toggle(),
child: const Icon(Icons.brightness_4),
),
),
);
},
);
}
}
:::tip
In a real application, you would use a persistent storage like shared_preferences or hive. See the Advanced Patterns folder for a storage implementation using path_provider.
:::