rive-app / rive-app/rive-android

Compose Rive() composable: ~370ms blank gap between first draw pass and actual bitmap content

Open
#452 1 comment 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Kotlin
Stars
538
Forks
66
PR merge metrics
No merged PRs in 30d

Description

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:

  1. Pre-parse a .riv file via RiveFile.fromSource(RiveFileSource.Bytes(bytes), sharedWorker) at
    app startup (splash screen).
  2. Cache the parsed RiveFile in a singleton.
  3. 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()
      },
  )
  1. 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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the Compose-native Rive() path from composition and its draw pass through onBitmapAvailable, using the supplied rememberArtboard, StateMachine, and rememberViewModelInstance reproduction. Compare the first draw timing with bitmap readiness on a physical Android device. Done means visible Rive content appears on the first draw or within 1–2 frames, without the reported blank gap.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, kotlin
Domain
mobile, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.