Documentation
Literal Patching
This is hotter than hot reload.
When your edit only changes a literal value, HotSwan skips the entire incremental compilation step and patches the value directly on the running device. The result is visible in under 50 milliseconds from the moment you save the file.
This makes it practical to fine tune colors, spacing, font sizes, and text by eye, iterating as fast as you can type. Resource value changes in XML files (strings, colors, dimensions) are also patched through the same fast path. No build, no class swap, no recomposition delay.
What is literal patching
HotSwan maintains a secondary representation of every constant expression in your composable tree. When the plugin detects that a saved file differs only in constant values, it bypasses the entire build system and resolves the new values against the existing representation on device. The Compose runtime then reconciles the updated constants within the current frame boundary, so the change appears on the very next draw pass.
Because the build toolchain is never invoked, the entire round trip from keystroke to pixel is measured in tens of milliseconds rather than seconds.
What qualifies as a literal change
A literal change is any edit that only modifies constant values inside a composable function body. If the edit does not add, remove, or reorder any function calls or control flow, it qualifies for the fast path.
- String literals: changing
"Hello"to"Hello, World" - Integer and float literals: changing
16.dpto24.dp, or0.5fto0.8f - Color hex values: changing
Color(0xFF6C5CE7)toColor(0xFFFF5722) - Long and double literals: any numeric constant that the compiler treats as a fixed value
String template changes are also supported. If you change the fixed text portions of a template like "Total: $count items", the fixed fragments are patched while the dynamic parts remain unchanged.
How it works
Normal hot reload goes through the full build pipeline. Literal patching skips straight to the result.
When you save a file, HotSwan checks whether the change is limited to constant values. If it is, the build system is bypassed entirely. The new values are sent directly to the device and applied on the next frame. If the change involves anything beyond literals, the normal pipeline runs automatically.
Examples
Here are common editing patterns that trigger literal patching.
Change a color
@Composable
fun ProfileCard() {
val accent = Color(0xFF6C5CE7)
Box(
modifier = Modifier
.background(accent)
)
}@Composable
fun ProfileCard() {
val accent = Color(0xFFFF5722)
Box(
modifier = Modifier
.background(accent)
)
}Adjust spacing and size
Box(
modifier = Modifier
.padding(16.dp)
.size(100.dp)
)Box(
modifier = Modifier
.padding(24.dp)
.size(150.dp)
)Update text content
Text(
text = "Welcome back",
fontSize = 18.sp,
)Text(
text = "Hello, World",
fontSize = 24.sp,
)Change a resource value
Editing existing values in strings.xml, colors.xml, or dimens.xml also triggers the fast path.
<string name="greeting">Hello</string>
<color name="primary">#6C5CE7</color>
<dimen name="card_padding">16dp</dimen><string name="greeting">Welcome back</string>
<color name="primary">#FF5722</color>
<dimen name="card_padding">24dp</dimen>One edit, many updates
When you store a literal in a local variable and reference it in multiple places, changing that single value updates every usage at once. For example, defining a color at the top of a composable and using it in three different modifiers means all three update on the same frame.
@Composable
fun Dashboard() {
val accent = Color(0xFF6C5CE7)
// All three pick up the new color instantly
Box(modifier = Modifier.background(accent))
Text(color = accent, text = "Status")
Divider(color = accent)
}Changing accent to a different hex value updates the background, text color, and divider in a single pass. This is useful for quickly iterating on a color palette or design system token without rebuilding.
When it falls back
Literal patching only applies when the edit is confined to constant values. If your edit also changes structure (adding a composable call, removing a parameter, changing control flow), HotSwan detects this and falls back to the normal hot reload path. The fallback is automatic and transparent.
A few specific cases that do not qualify for the fast path:
- Adding or removing lines: If the line count of the function changes, the edit is not literal only.
- Changing variable names or types: Renaming a variable or changing its type is a structural change.
- Top level constants: Literals defined outside composable function bodies (such as
const valor top levelval) are not covered by the compiler plugin's wrapping. Move them inside the composable body if you want instant patching.
In all of these cases, HotSwan falls back to the normal hot reload path and applies the change as usual. The only difference is speed: literal patching completes in under 50 milliseconds, while the normal path takes a few seconds depending on your project size.