Summary
The issue stems from Flutter’s “Stateful Hot Reload” being disabled for the current run configuration, causing the IDE to fall back to a full hot restart each time you press the hot‑reload button. This typically happens when:
- The application is launched in profile or release mode instead of debug.
--no-hot-reload(or--no-pause-isolates) is passed implicitly.- The
WidgetsBindingObserveror a splash screen implementation forces a widget tree rebuild that mimics a restart.
Understanding why Flutter decides to restart rather than reload lets you restore true hot‑reload behavior.
Root Cause
- Debug mode not active – Hot reload works only in debug builds. If the app is started with
flutter run --profileor--release, the tooling will perform a hot restart. --disable-service-auth-codes/--no-hot-reloadflags – Some custom launch scripts or IDE launch configurations add these flags, disabling hot reload.WidgetsBinding.instance?.addPostFrameCallbackinside the splash logic that forcesrunApp()again, effectively resetting the state on every reload.flutter_toolcache corruption – A staleflutter_tool.stampcan trick the engine into thinking the VM is detached, causing a restart fallback.
Why This Happens in Real Systems
- CI/CD pipelines often run Flutter in profile/release mode to test performance, unintentionally copying those flags into local IDE launch configs.
- Third‑party splash screen plugins (e.g.,
flutter_native_splash) sometimes inject native code that restarts the Dart isolate on each frame when the splash view is dismissed. - Team‑wide scripts that prepend
--no-hot-reloadtoflutter runto avoid accidental state leaks in shared machines. - IDE cache synchronization bugs – when the IDE’s “Flutter Daemon” loses connection, the fallback is a hot restart.
Real-World Impact
- Lost debugging context – breakpoints and variable watches disappear after every reload.
- Longer development cycles – a full restart takes 2–4 seconds vs. < 1 second for hot reload.
- State‑related bugs go unnoticed because the app always starts from the splash screen, masking issues that only appear after a true hot reload.
- Team frustration – junior developers assume hot reload works and spend hours troubleshooting UI changes that never appear.
Example or Code (if necessary and relevant)
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
# Correct launch command
flutter run --debug
# Incorrect launch that forces hot restart
flutter run --profile --no-hot-reload
How Senior Engineers Fix It
- Verify the run mode
- Run
flutter devicesand ensure the device showsdebugnext to the app. - Restart the app with
flutter run --debug.
- Run
- Check launch configuration
- In VS Code, open
.vscode/launch.jsonand remove anyargsthat include--no-hot-reloador--profile. - In Android Studio/IntelliJ, open Run/Debug Configurations → Flutter and set Mode to Debug.
- In VS Code, open
- Clear the tool’s stamp files
rm -rf ~/.flutter_tool_state flutter clean - Audit splash implementation
- Ensure the splash screen does not call
runAppagain after the first frame. - If using
flutter_native_splash, runflutter pub run flutter_native_splash:removeand test.
- Ensure the splash screen does not call
- Validate daemon connection
- Open the Flutter Daemon console; if it disconnects, restart the IDE and the Dart Analysis Server.
- Re‑install the Flutter SDK (last resort)
- Corrupted binaries can misreport capabilities; reinstall from the official channel.
Why Juniors Miss It
- Assume hot reload is always available and overlook the run mode selection dropdown.
- Focus on UI code and ignore the launch scripts or IDE configuration files.
- Misinterpret the splash screen restart as a bug in the app rather than a tooling issue.
- Lack experience with the distinction between hot reload (preserves state) and hot restart (re‑initializes the Dart VM).