Skip to content

fix(android): Release PreviewView when the React view is dropped - #4185

Open
vgorte wants to merge 1 commit into
margelo:mainfrom
vgorte:fix/android-preview-view-drop-cleanup
Open

fix(android): Release PreviewView when the React view is dropped#4185
vgorte wants to merge 1 commit into
margelo:mainfrom
vgorte:fix/android-preview-view-drop-cleanup

Conversation

@vgorte

@vgorte vgorte commented Sep 7, 2026

Copy link
Copy Markdown

Fixes #4180

Problem

HybridPreviewView only detached its PreviewView from the preview output when the
previewOutput prop changed, and only removed the stream-state observer in dispose(),
which Nitro does not call on unmount. After every <Camera> unmount the PreviewView
and its SurfaceView stayed reachable via Preview.mSurfaceProvider and via the
hybrid's own field until Hermes happened to collect the JS wrappers.

Change

onDropView() and dispose() now release the view on the UI thread: remove the
observer, remove the surface provider from the output, drop the PreviewView reference.
Prop setters and connect/disconnect return early once the view is dropped.

Evidence

Reporter's 300 ms mount/unmount toggle, emulator API 36, heap dump after a forced Java GC
(no Hermes GC), instance counts via shark-cli:

after N cycles before, N=30 before, N=200 after, N=30 after, N=200
PreviewView / SurfaceView 31 201 0 0

Note on the dump in the issue: it counts HybridPreviewView / HybridPreviewOutput
instances, which are JS-owned and only disappear with a Hermes GC. That count is the same
with and without this change; the SurfaceView count above is the one that was leaking.

Test

visioncamera.nativepreviewview.harness.tsx: re-uses one preview output across an old
and a replacement NativePreviewView in a single update. Native retention is not
observable from JS, so this guards the interaction the change touches rather than the
leak itself. Heap dumps available on request.

Nitro does not call `dispose()` on unmount, so the `PreviewView` and its
`SurfaceView` stayed reachable after every unmount. `onDropView()` now
removes the stream-state observer, detaches the surface provider and
drops the view reference.

Fixes margelo#4180
@vercel

vercel Bot commented Sep 7, 2026

Copy link
Copy Markdown

@vgorte is attempting to deploy a commit to the Margelo Team on Vercel.

A member of the Team first needs to authorize it.

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.

馃悰 Android: every <Camera> mount leaks its SurfaceView and camera output stream

1 participant