Skip to content

fix(android): Make FirstDrawDoneListener cleanup OnGlobalLayoutListener after use#5567

Merged
romtsn merged 2 commits into
mainfrom
rz/fix/first-draw-done-listener-leak
Jun 19, 2026
Merged

fix(android): Make FirstDrawDoneListener cleanup OnGlobalLayoutListener after use#5567
romtsn merged 2 commits into
mainfrom
rz/fix/first-draw-done-listener-leak

Conversation

@romtsn

@romtsn romtsn commented Jun 18, 2026

Copy link
Copy Markdown
Member

📜 Description

The OnGlobalLayoutListener registered in onDraw() to defer removal of the OnDrawListener was never itself removed from the ViewTreeObserver. In single-Activity apps (e.g. React Native), this caused an unbounded per-navigation leak — one listener per registerForNextDraw call, each pinning the dismissed screen's view tree.

The fix makes the OnGlobalLayoutListener remove itself after firing.

Note: this bug was inherited from Firebase's original implementation, which has the same issue.

💡 Motivation and Context

~80–100 MB of Java heap retained after ~50 navigations in the reporter's RN app, with leaked listener count tracking navigations 1:1.

💚 How did you test it?

  • Added a regression test that verifies mOnGlobalLayoutListeners is empty after the cleanup fires
  • Confirmed the test fails without the fix and passes with it

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

🔮 Next steps

…er after use

The OnGlobalLayoutListener registered in onDraw() to defer removal of the
OnDrawListener was never itself removed. In single-Activity apps (e.g. React
Native), this caused an unbounded per-navigation leak on the ViewTreeObserver,
accumulating one listener per registerForNextDraw call.

Make the OnGlobalLayoutListener remove itself after firing.

Fixes JAVA-545
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@linear-code

linear-code Bot commented Jun 18, 2026

Copy link
Copy Markdown

JAVA-545

@sentry

sentry Bot commented Jun 18, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
SDK Size io.sentry.tests.size 8.44.0 (1) release

⚙️ sentry-android Build Distribution Settings

@romtsn romtsn marked this pull request as ready for review June 18, 2026 12:07
@github-actions

Copy link
Copy Markdown
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 385.04 ms 477.47 ms 92.43 ms
Size 0 B 0 B 0 B

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
a416a65 333.78 ms 410.37 ms 76.59 ms
d15471f 304.55 ms 408.43 ms 103.87 ms
ca6b6d8 380.45 ms 460.38 ms 79.93 ms
c8125f3 397.65 ms 485.14 ms 87.49 ms
b936425 302.69 ms 372.86 ms 70.17 ms
ed33deb 334.19 ms 362.30 ms 28.11 ms
cf708bd 408.35 ms 458.98 ms 50.63 ms
eb95ded 317.51 ms 369.08 ms 51.57 ms
a5ab36f 320.47 ms 389.77 ms 69.30 ms
80fd6ad 321.06 ms 375.79 ms 54.73 ms

App size

Revision Plain With Sentry Diff
a416a65 1.58 MiB 2.12 MiB 555.26 KiB
d15471f 1.58 MiB 2.13 MiB 559.54 KiB
ca6b6d8 0 B 0 B 0 B
c8125f3 1.58 MiB 2.10 MiB 532.32 KiB
b936425 0 B 0 B 0 B
ed33deb 1.58 MiB 2.13 MiB 559.52 KiB
cf708bd 1.58 MiB 2.11 MiB 539.71 KiB
eb95ded 0 B 0 B 0 B
a5ab36f 1.58 MiB 2.12 MiB 555.26 KiB
80fd6ad 0 B 0 B 0 B

@runningcode runningcode 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.

nice fix!

@romtsn romtsn merged commit 8da852c into main Jun 19, 2026
69 checks passed
@romtsn romtsn deleted the rz/fix/first-draw-done-listener-leak branch June 19, 2026 09:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants