hotReload method
Hot reload a module while preserving its state
This method:
- Captures the current module state
- Calls onBeforeReload (dispose old module)
- Calls onAfterReload (initialize new module)
- Restores the captured state
Implementation
Future<void> hotReload(
String moduleId, {
Future<void> Function()? onBeforeReload,
Future<void> Function()? onAfterReload,
List<String>? stateKeysToPreserve,
}) async {
if (!kDebugMode) {
AirLogger.warning('HMR is only available in debug mode');
return;
}
AirLogger.info('Starting hot reload', context: {'moduleId': moduleId});
try {
// 1. Capture state to preserve
if (stateKeysToPreserve != null && stateKeysToPreserve.isNotEmpty) {
final stateToPreserve = <String, dynamic>{};
for (final key in stateKeysToPreserve) {
final controller = Air().debugStates[key];
if (controller != null) {
stateToPreserve[key] = controller.value;
}
}
preserveState(moduleId, stateToPreserve);
}
// 2. Notify listeners before reload
_notifyListeners(moduleId);
// 3. Dispose old module
if (onBeforeReload != null) {
await onBeforeReload();
}
// 4. Initialize new module
if (onAfterReload != null) {
await onAfterReload();
}
// 5. Restore state
final preserved = restoreState(moduleId);
if (preserved != null) {
for (final entry in preserved.entries) {
try {
Air()
.state(entry.key, initialValue: entry.value)
.setValue(entry.value, sourceModuleId: moduleId);
} catch (e) {
AirLogger.warning(
'Failed to restore state key',
context: {'key': entry.key, 'error': e.toString()},
);
}
}
}
AirLogger.info('Hot reload completed', context: {'moduleId': moduleId});
} catch (e, stack) {
AirLogger.error(
'Hot reload failed',
context: {'moduleId': moduleId, 'error': e.toString()},
);
if (kDebugMode) {
debugPrintStack(stackTrace: stack);
}
rethrow;
}
}