Skip to content

fix(android): Always remove FirstDrawDoneListener after the first draw - #6152

Merged
runningcode merged 2 commits into
mainfrom
no/first-draw-listener-removal
Oct 22, 2026
Merged

runningcode merged 2 commits into
mainfrom
no/first-draw-listener-removal

Conversation

@runningcode

Copy link
Copy Markdown
Contributor

📜 Description

FirstDrawDoneListener now removes itself by posting the removal to the main thread. Before, it waited for the next global layout.

💡 Motivation and Context

You can't remove an OnDrawListener from inside onDraw (API 26+ throws). So the listener registered an OnGlobalLayoutListener and removed itself from there. But a draw isn't always followed by a layout pass. On a static screen, the listener stayed registered and ran on every frame (as a no-op), and it kept its callback reachable. That callback captures ActivityLifecycleIntegration and the ttid/ttfd spans. ActivityLifecycleIntegration registers a new listener on every onActivityResumed, so these could pile up on the decor view until the next layout.

It isn't a memory leak: everything is only reachable from the decor view's ViewTreeObserver and dies with the activity. The fix makes the removal happen every time and drops the extra layout listener.

💚 How did you test it?

Updated FirstDrawDoneListenerTest: the listener is now removed after onDraw without any layout pass.

📝 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.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.

🔮 Next steps

Consider registering only once per activity in ActivityLifecycleIntegration.onActivityResumed, instead of on every resume.

🤖 Generated with Claude Code

@sentry

sentry Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

📲 Install Builds

Android

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

⚙️ sentry-android Build Distribution Settings

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

great catch!

@runningcode
runningcode marked this pull request as ready for review October 22, 2026 14:28
runningcode and others added 2 commits October 22, 2026 16:32
The listener was removed from an OnGlobalLayoutListener, which only runs if
a layout pass follows the draw. On a static screen it stayed registered and
ran on every frame, retaining its callback. Post the removal to the main
thread instead so it always happens.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@runningcode
runningcode force-pushed the no/first-draw-listener-removal branch from 6afd9db to 36896f1 Compare October 22, 2026 14:34
@runningcode
runningcode enabled auto-merge (squash) October 22, 2026 14:38
@runningcode
runningcode merged commit 31b2243 into main Oct 22, 2026
67 of 69 checks passed
@runningcode
runningcode deleted the no/first-draw-listener-removal branch October 22, 2026 14:54
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