When using the Compose-native Rive() composable, there is a significant delay (~370ms) between when compose first draws the Rive composable's area on screen and when Rive actually produces visible bitmap content via onBitmapAvailable.
During this gap, the composable's draw area is present in the layout but renders nothing (transparent/empty), while sibling composables (e.g. Icon()) display their content immediately on the same draw pass.
Environment:
- rive-android: 11.4.0
- Jetpack Compose
- Android 16
- Tested on physical device
Reproduction:
- Pre-parse a .riv file via RiveFile.fromSource(RiveFileSource.Bytes(bytes), sharedWorker) at
app startup (splash screen).
- Cache the parsed RiveFile in a singleton.
- In a Composable, use the cached file:
val artboard = rememberArtboard(cachedFile)
val stateMachine = remember(artboard) { StateMachine.fromArtboard(artboard, null) }
val vmi = rememberViewModelInstance(cachedFile)
Rive(
file = cachedFile,
playing = true,
artboard = artboard,
stateMachine = stateMachine,
viewModelInstance = vmi,
fit = Fit.Contain(),
onBitmapAvailable = { /* log: bitmap ready */ },
modifier = Modifier.size(32.dp).drawWithContent {
// log: draw pass
drawContent()
},
)
- Place the Rive() composable alongside a standard Icon() in the same Row/Box.
Observed behavior:
Measured timestamps relative to NavBarConfigRepository.refresh() call (anchor):
Rive() composable enters composition: +1035ms
- Compose draw pass —
drawWithContent fires for Rive(): +1442ms
- Compose draw pass —
drawWithContent fires for sibling Icon(): +1445ms
onBitmapAvailable callback fires (Rive produces actual content): +1812ms
The Rive() composable participates in the Compose draw pass at the same time as static Icon() composables (within 3ms). However, Rive's actual bitmap content doesn't appear until 370ms later.
During this 370ms gap, the Rive area on screen is blank/transparent while sibling icons are already visible. This creates a noticeable visual delay.
Expected behavior: Rive() composable should produce visible content on its first draw pass (or within 1-2 frames), consistent with how other Compose drawing primitives behave. The file is already fully parsed and cached - no I/O or parsing should be needed at render time.
Context:
- The .riv file is small (967 bytes), pre-parsed via shared CommandQueue worker ~800ms before the
composable enters composition. Parse itself takes ~70ms.
- rememberArtboard() and rememberViewModelInstance() are called before Rive() in the same
composition.
- playing = true is set, so the state machine should advance immediately.
- The delay is consistent across cold starts (~350-400ms each time).
- This is not a TextureView surface init issue — we specifically migrated from
AndroidView(RiveAnimationView) (which had ~500ms TextureView surface delay) to Compose-native
Rive() to avoid that. The Compose path is faster but still has this internal gap.
When using the Compose-native Rive() composable, there is a significant delay (~370ms) between when compose first draws the Rive composable's area on screen and when Rive actually produces visible bitmap content via onBitmapAvailable.
During this gap, the composable's draw area is present in the layout but renders nothing (transparent/empty), while sibling composables (e.g. Icon()) display their content immediately on the same draw pass.
Environment:
Reproduction:
app startup (splash screen).
val artboard = rememberArtboard(cachedFile)
val stateMachine = remember(artboard) { StateMachine.fromArtboard(artboard, null) }
val vmi = rememberViewModelInstance(cachedFile)
Observed behavior:
Measured timestamps relative to NavBarConfigRepository.refresh() call (anchor):
Rive()composable enters composition: +1035msdrawWithContentfires forRive(): +1442msdrawWithContentfires for siblingIcon(): +1445msonBitmapAvailablecallback fires (Rive produces actual content): +1812msThe Rive() composable participates in the Compose draw pass at the same time as static Icon() composables (within 3ms). However, Rive's actual bitmap content doesn't appear until 370ms later.
During this 370ms gap, the Rive area on screen is blank/transparent while sibling icons are already visible. This creates a noticeable visual delay.
Expected behavior: Rive() composable should produce visible content on its first draw pass (or within 1-2 frames), consistent with how other Compose drawing primitives behave. The file is already fully parsed and cached - no I/O or parsing should be needed at render time.
Context:
composable enters composition. Parse itself takes ~70ms.
composition.
AndroidView(RiveAnimationView) (which had ~500ms TextureView surface delay) to Compose-native
Rive() to avoid that. The Compose path is faster but still has this internal gap.