Skip to content

Dynamic Scaling

Rebound dynamically adjusts budget thresholds based on the current interaction state. A composable that would violate its budget during idle may be perfectly acceptable during a fast scroll or animation.

Rebound detects four interaction states:

StateMultiplierMeaning
IDLE1.0xNo active interaction. Base budgets apply.
SCROLLING2.0xThe user is actively scrolling a lazy list.
ANIMATING1.5xAn animation or transition is running.
USER_INPUT1.5xThe user is actively interacting (typing, dragging, etc.).

Interaction state is inferred from the recomposition patterns of budget-classified composables:

When LIST_ITEM composables exceed 20 recompositions per second collectively, Rebound infers that a scroll is in progress. This works because lazy list items only recompose rapidly when the list is being scrolled.

When ANIMATED composables exceed 30 recompositions per second, Rebound infers that an animation is active. This captures animate* transitions, Animatable updates, and physics-based animations.

When INTERACTIVE composables exceed 10 recompositions per second, Rebound infers that the user is actively interacting. This captures text field input, slider drags, and other high-frequency input events.

The interaction state transitions back to IDLE when the trigger condition is no longer met. There is a brief cooldown period to avoid flickering between states.

The effective budget for any composable is:

effectiveBudget = baseBudget * interactionMultiplier

Examples:

ComposableBase BudgetDuring SCROLLING (2.0x)During ANIMATING (1.5x)
SCREEN (3/s)3/s6/s4.5/s
CONTAINER (10/s)10/s20/s15/s
LIST_ITEM (60/s)60/s120/s90/s
ANIMATED (120/s)120/s240/s180/s

Without dynamic scaling, scrolling a LazyColumn would trigger violations on every list item composable. A list item recomposing at 50/s during a fast scroll is expected behavior — the item is being composed, scrolled off screen, and recycled. Flagging this as a violation produces noise.

With dynamic scaling, the same 50/s rate during scroll (effective budget 120/s) is clearly within bounds. But 50/s during IDLE (effective budget 60/s) is flagged — something is causing the list items to recompose rapidly even though nobody is scrolling.

The interaction state is reported in every violation message:

W/Rebound: [VIOLATION] ProductCard — 70 recomp/s (budget: 60, class: LIST_ITEM)
-> interaction: IDLE

This IDLE annotation tells you the violation is real — the composable exceeded its budget even without active scrolling.