Hot Reload
XWidget supports hot reload of fragments and value resources during a Flutter debug session. Edit an XML file in your IDE, save, and the running app updates immediately — no restart, no loss of app state.
Requirements
- A debug build running in a Dart VM with service extensions enabled. This is the
default for
flutter runand IDE debug sessions. - An IDE plugin that supports XWidget hot reload:
- IntelliJ IDEA / Android Studio — the Flutter XWidget IntelliJ plugin (version 0.1.7+).
- VSCode — the Flutter XWidget VSCode extension (version 0.1.0+).
What Gets Hot Reloaded
- Fragment XML files under your configured
fragmentsPath. Edits propagate as a full fragment replacement. - Value XML files under your configured
valuesPath. Edits re-parse the file and merge new values into the active value bundle.
What does not hot reload:
- Changes to Dart code — those go through Flutter's standard hot reload.
- Changes to your inflater, icon, or controller specs — these require regeneration
(
xc generate) and a full restart. - Changes to
xwidget_config.yaml— same; requires regeneration and restart.
How It Works
When you save a fragment or value file with a running debug session, the IDE plugin:
- Detects the save event.
- Opens a connection to the running app's Dart VM service.
- Calls one of two service extensions exposed by
LocalResources:ext.xwidget.updateFragmentfor fragment saves.ext.xwidget.updateValuesfor value saves.
- Sends the new file content as a parameter.
The service extension handlers:
- Update the in-memory fragment or value bundle with the new content.
- Clear XWidget's parsed XML cache (for fragments).
- Call
WidgetsBinding.instance.reassembleApplication(), which causes Flutter to rebuild the widget tree from the root.
The rebuilt tree sees the updated bundles and renders accordingly. Dependencies, app state, and navigation all persist.
Debouncing
The IDE plugins debounce saves at 200ms to coalesce rapid edits (e.g., auto-save on typing). A short status indicator in the IDE reflects the reload state.
Limitations
File additions and deletions require restart. Hot reload only handles content changes to files that existed when the app started. Adding a new fragment file or deleting an existing one is not picked up — restart the debug session.
Note
A fragment that's referenced via <fragment name="new_fragment"/> for the first
time during hot reload will throw a "fragment not found" error unless that file
existed at startup. The fix is a restart, not a bug in hot reload.
Cloud resources don't hot reload. CloudResources loads from a cloud-delivered
bundle at startup and registers no file-watch service extensions — its asset-bundle
fallback doesn't change that, because assets are a frozen snapshot that the IDE
plugin can't inject into. Hot reload requires the running Resources instance to be
a LocalResources. For local development, use LocalResources (the default) and hot
reload works as described. To test fragment changes against a cloud project, deploy
and publish to a staging channel (xc cloud deploy, then xc cloud publish -c staging)
and restart.
Debug-only
The service extensions are gated on kDebugMode — they are never registered in release
builds. The file watchers in the IDE plugins do nothing when no debug session is
attached. There is no release-mode exposure of hot reload surfaces.
Troubleshooting
Saves don't trigger a reload. Confirm the debug session is running and the IDE status bar shows an active XWidget connection. Restarting the debug session re-registers the service extensions.
Changes load but app shows stale UI. Hot reload relies on
reassembleApplication(), which rebuilds from the widget tree root. Widgets that
bypass this (custom render objects, explicit keys that aren't invalidated, image
caches) may show stale content. A full hot restart (R in flutter run) always
resolves this.
Fragment parse error after reload. The updated file has a syntax error or references a widget that isn't registered. Fix the XML in the IDE and save again — reload is re-triggered.
See IntelliJ Plugin and VSCode Extension for installation.