You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
FirstDrawDoneListener still leaks one react-native-screens fragment per navigation after #5567 #6357
React Native app (RN 0.81.5, new architecture) with a native stack (react-native-screens 4.17.1) and reactNavigationIntegration({ enableTimeToInitialDisplay: true }).
Push a screen onto the stack, wait for it to render, then go back. Repeat 11 times.
Force a GC and take a heap dump (am dumpheap -g).
Expected Result
The popped ScreenStackFragments are collected.
Actual Result
Each push leaves one ScreenStackFragment and its whole native view tree in memory. On a 256 MB heap device the app ends in OutOfMemoryError after long sessions.
#5567 (fix for #5495) makes the OnGlobalLayoutListener call view.getViewTreeObserver().removeOnGlobalLayoutListener(this). That does not work for the views RNSentryReactFragmentLifecycleTracer registers:
onDraw() adds the layout listener to the window's ViewTreeObserver.
A static screen has no layout pass after its first draw, so the listener does not run yet.
The next layout pass comes when the screen is popped. The fragment view is already detached, so view.getViewTreeObserver() returns the view's own floating observer, not the window's.
The remove call does nothing. The listener stays on the window's observer and keeps the detached view alive.
Fix
#6152 fixes it: it posts the OnDrawListener removal to the main thread right after the draw and drops the layout listener. We applied the same change with patch-package (a copy of the listener in @sentry/react-native used by RNSentryReactFragmentLifecycleTracer) and ran the same test:
Class
Before
After 11 cycles
ScreenStackFragment
3
4
FirstDrawDoneListener
1
1
ReactViewGroup
143
190
This matches enableTimeToInitialDisplay: false, so the leak is gone with TTID still on. The #6152 description says the old behaviour "isn't a memory leak" because everything dies with the activity. In a single-Activity React Native app the activity lives for the whole session, so it is an unbounded leak. We would be glad to see #6152 merged.
Activity
linear-code commentedon Oct 22, 2026
JAVA-791