Skip to content

fix(android): don't re-acquire a disposed Rive file on view re-attach - #319

Merged
mfazekas merged 4 commits into
mainfrom
fix/android-disposed-file-reattach
Jul 6, 2026
Merged

mfazekas merged 4 commits into
mainfrom
fix/android-disposed-file-reattach

Conversation

@mfazekas

@mfazekas mfazekas commented Jul 6, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes a production crash: after a RiveView is dropped, dispose() releases the controller (which releases its File), but rendererAttributes.resource still caches a ResourceRiveFile pointing at the now-disposed file. If the Android view is later attached to a window again (e.g. Fabric view recycling), RiveAnimationView.onAttachedToWindow reloads that stale resource and throws Cannot acquire a disposed object in RiveFileController.setFile -> NativeObject.acquire.

dispose() now nulls rendererAttributes.resource before releasing the controller (mirrors RiveAnimationView.saveControllerState()), and onAttachedToWindow drops a cached ResourceRiveFile whose file has no cpp object before calling super.

Reproduced and verified with the included Disposed File Re-attach reproducer page. The re-attach itself is driven by rive-debug-utils, a new private workspace package with an Android-only Nitro hybrid object that captures the dropped Android view and re-attaches it the way view recycling would; it autolinks into all three example apps. The reproducer crashes with the exact production stack before the fix and passes after.

Same fix as #318, which targets the feat/use-viewmodel-instance-async branch (its android/src/legacy variant).

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remaining comments which cannot be posted as a review comment to avoid GitHub Rate Limit

ktlint

🚫 [ktlint] standard:wrapping reported by reviewdog 🐶
Missing newline after ","


🚫 [ktlint] standard:wrapping reported by reviewdog 🐶
Missing newline before ")"


🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Argument should be on a separate line (unless all arguments can fit a single line)


🚫 [ktlint] standard:argument-list-wrapping reported by reviewdog 🐶
Missing newline before ")"

import com.margelo.nitro.core.Promise

/**
* Test helper for the example apps: simulates what Fabric view recycling does

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great!

@HayesGordon HayesGordon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks for this, and the testing is great.

@mfazekas
mfazekas force-pushed the fix/android-disposed-file-reattach branch from 83ba9ac to 273f1b9 Compare July 6, 2026 12:03
@mfazekas
mfazekas enabled auto-merge (squash) July 6, 2026 12:11
mfazekas added 4 commits July 6, 2026 14:59
After a RiveView is dropped, dispose() releases the controller (which
releases its File), but rendererAttributes.resource still caches a
ResourceRiveFile pointing at the now-disposed File. If the Android view
is later attached to a window again (e.g. Fabric view recycling),
RiveAnimationView.onAttachedToWindow reloads that stale resource and
crashes with "Cannot acquire a disposed object" in
RiveFileController.setFile -> NativeObject.acquire.

Null rendererAttributes.resource in dispose() (mirrors
RiveAnimationView.saveControllerState()) and drop a stale dead-file
resource in onAttachedToWindow before calling super.

Reproduced and verified with the new Disposed File Re-attach reproducer
page, backed by a dev-only RiveViewReattach native module in the example
app that re-attaches the dropped Android view like view recycling would:
FAIL (crash) before the fix, PASS after.
…ive helper

The reproducer page is reachable from the Expo examples via the shared
PagesList, but the RiveViewReattach helper only exists in the bare
example app — pressing Run there would throw.
…tils nitro package

Private workspace package (not published) with an Android-only Nitro
HybridObject exposing captureView/reattachCapturedView/releaseCapturedView.
Autolinked into all three example apps (bare + both Expo apps via prebuild),
replacing the bare-example-only RiveViewReattach bridge module, so the
Disposed File Re-attach reproducer works everywhere.
Root 'yarn nitrogen' globs the whole repo for .nitro.ts files, so the new
package's spec leaked into the library's generated output (also via the
workspace symlinks in the examples' node_modules). Ignore it, and extend
the .editorconfig ktlint exemption to the package's generated Kotlin.
@mfazekas
mfazekas force-pushed the fix/android-disposed-file-reattach branch from 273f1b9 to 2cf0aaf Compare July 6, 2026 12:59
@mfazekas
mfazekas merged commit 4259723 into main Jul 6, 2026
9 checks passed
@mfazekas
mfazekas deleted the fix/android-disposed-file-reattach branch July 6, 2026 13:13
mfazekas pushed a commit that referenced this pull request Jul 6, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.4.14](v0.4.13...v0.4.14)
(2026-07-06)


### Bug Fixes

* **android:** bump rive-android to 11.6.2
([#317](#317))
([ae66b24](ae66b24))
* **android:** don't re-acquire a disposed Rive file on view re-attach
([#319](#319))
([4259723](4259723))
* **hooks:** no-op stale property setter calls after dispose
([#316](#316))
([dbb4dd7](dbb4dd7))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
mfazekas added a commit that referenced this pull request Jul 7, 2026
Merges `main` up to the 0.4.14 release into the iOS experimental branch.
No conflicts.

Notable changes pulled in:
1. fix(android): don't re-acquire a disposed Rive file on view re-attach
(#319)
2. fix(hooks): no-op stale property setter calls after dispose (#316)
3. fix(android): bump rive-android to 11.6.2 (#317) — resolves to 11.6.2
here (up from 11.6.1)

On the #319 native fix: this branch has the legacy/new Android backend
split, so git's rename detection applied the fix to the
`android/src/legacy` variant of `RiveReactNativeView.kt` — which is
correct, since the crash is a property of upstream `RiveAnimationView`'s
cached `rendererAttributes.resource`. The `android/src/new` backend is a
separate `TextureView`/`CommandQueue` implementation with no such code
path, so the same tweak neither applies nor is needed there. A re-attach
lifecycle bug in the new backend, if any, would be a separate fix.

---------

Co-authored-by: Rive Engineering <60802183+rive-engineering@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants