Skip to content

fix(android): Fix Activity memory leak in ScreenDummyLayoutHelper due to unreleased view references and missing lifecycle cleanup#3638

Merged
t0maboro merged 20 commits intosoftware-mansion:mainfrom
l2hyunwoo:feature/#3636
Apr 10, 2026
Merged

fix(android): Fix Activity memory leak in ScreenDummyLayoutHelper due to unreleased view references and missing lifecycle cleanup#3638
t0maboro merged 20 commits intosoftware-mansion:mainfrom
l2hyunwoo:feature/#3636

Conversation

@l2hyunwoo
Copy link
Copy Markdown
Contributor

@l2hyunwoo l2hyunwoo commented Feb 12, 2026

Description

Fix Activity memory leak in ScreenDummyLayoutHelper caused by unreleased view references (CoordinatorLayout, AppBarLayout, Toolbar, View) when the host Activity is destroyed.

The helper created dummy views using Activity-scoped Context to measure header heights, but never released these references on Activity destruction. This created a strong reference chain (ScreenDummyLayoutHelper → Views → ContextThemeWrapper → Activity) that prevents GC of destroyed Activities.

Closes: #3636

Changes

  • Changed view fields from lateinit var to nullable var? = null to allow reference release
  • Always register LifecycleEventListener in constructor (regardless of init success)
  • Keep listener registered across Activity lifecycle (never remove it) to ensure onHostDestroy is always called
  • Release all view references, reset cache, and reset isLayoutInitialized in onHostDestroy to break the reference chain and allow re-initialization on next onHostResume
  • Wrap computeDummyLayout in synchronized(this) block with null-safe local variables, returning 0.0f as fallback when views are already cleaned up
  • Synchronize onHostDestroy cleanup on the same monitor to prevent race conditions

Screenshots / GIFs

Before

Screen.Recording.2026-03-12.at.14.48.04.mov

After

Screen.Recording.2026-03-12.at.14.49.34.mov

Test plan

  1. Launch a React Native app with native stack navigation using react-native-screens
  2. Navigate through screens to trigger ScreenDummyLayoutHelper initialization
  3. Trigger Activity recreation (dev reload, configuration change, or process restoration)
  4. Use Android Studio Memory Profiler or LeakCanary to verify the previous Activity is no longer retained
  5. Repeat to confirm no leak accumulation across multiple Activity recreations
  6. Verify header height computation still works correctly after Activity recreation (headers render with correct dimensions)

Checklist

  • Included code example that can be used to test this change.
  • Updated / created local changelog entries in relevant test files.
  • For visual changes, included screenshots / GIFs / recordings documenting the change.
  • For API changes, updated relevant public types.
  • Ensured that CI passes

- Convert lateinit var to nullable var for view fields
- Always register LifecycleEventListener regardless of init result
- Null all view references and reset state in onHostDestroy
- Add synchronized block to prevent race between compute and cleanup
@kkafar kkafar requested a review from t0maboro March 9, 2026 19:45
@t0maboro
Copy link
Copy Markdown
Contributor

t0maboro commented Mar 12, 2026

Hi @l2hyunwoo ,
Thanks for submitting this PR - I can confirm that it resolves the memory leak issue in the ScreenDummyLayoutHelper.

I hope you don't mind if I add a few additional changes to this PR to clean things up a bit. Also, based on the research I've done, I'm wondering if it might be better to rely on ActivityLifecycleCallbacks to listen for activity destruction events directly from the OS, rather than depending on React Native. Let me follow up with this PR.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes an Activity memory leak in ScreenDummyLayoutHelper where dummy views held strong references to destroyed Activities. The fix makes view fields nullable and adds cleanup via Application.ActivityLifecycleCallbacks.

Changes:

  • Changed view fields from lateinit var to nullable var? = null and added cleanUpViews() to null them out on Activity destruction
  • Added Application.ActivityLifecycleCallbacks to detect Activity destruction and trigger cleanup
  • Added a test reproduction file (Test3636.tsx) for the memory leak scenario

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
android/src/main/java/com/swmansion/rnscreens/utils/ScreenDummyLayoutHelper.kt Core fix: nullable view fields, lifecycle callback registration, cleanup logic
apps/src/tests/issue-tests/Test3636.tsx Test reproduction app for the memory leak
apps/src/tests/issue-tests/index.ts Exports the new test

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread android/src/main/java/com/swmansion/rnscreens/utils/ScreenDummyLayoutHelper.kt Outdated
Comment thread android/src/main/java/com/swmansion/rnscreens/utils/ScreenDummyLayoutHelper.kt Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread android/src/main/java/com/swmansion/rnscreens/utils/ScreenDummyLayoutHelper.kt Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread android/src/main/java/com/swmansion/rnscreens/utils/ScreenDummyLayoutHelper.kt Outdated
Comment thread android/src/main/java/com/swmansion/rnscreens/utils/ScreenDummyLayoutHelper.kt Outdated
@t0maboro t0maboro requested a review from kligarski April 1, 2026 18:37
Copy link
Copy Markdown
Contributor

@kligarski kligarski left a comment

Choose a reason for hiding this comment

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

Looks good to me but I'd wait for @kkafar's review before merging.

Copy link
Copy Markdown
Member

@kkafar kkafar left a comment

Choose a reason for hiding this comment

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

Hey, thanks for the contribution. I've left few remarks & question. Let's answer them before landing these changes.

Comment thread android/src/main/java/com/swmansion/rnscreens/utils/ScreenDummyLayoutHelper.kt Outdated
Comment thread android/src/main/java/com/swmansion/rnscreens/utils/ScreenDummyLayoutHelper.kt Outdated
Comment thread android/src/main/java/com/swmansion/rnscreens/utils/ScreenDummyLayoutHelper.kt Outdated
@t0maboro t0maboro requested a review from kkafar April 9, 2026 08:23
Copy link
Copy Markdown
Member

@kkafar kkafar left a comment

Choose a reason for hiding this comment

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

Looks ok. Let's roll this out and get some feedback.

@efstathiosntonas
Copy link
Copy Markdown

efstathiosntonas commented Apr 10, 2026

thank you guys for working hard on this one!

@kkafar is there an ETA for this? (I’m right on one step before rolling out a big release so sorry for the question 😅)

@t0maboro t0maboro merged commit 4336686 into software-mansion:main Apr 10, 2026
5 checks passed
@mduleone
Copy link
Copy Markdown

Thank you all for this! We just discovered this issue in our app and stumbled upon the PR. Delighted to see that it's merged already! We're still on RN 0.81.5 and react-native-screens 4.16.0. What are the chances that this will be patched into a version that still supports RN 0.81?

@kkafar
Copy link
Copy Markdown
Member

kkafar commented Apr 12, 2026

The 4.25.0 release waits for us being ready with Tabs API (stabilisation). I plan to release it ASAP, but first planned release date was ~ 1 month ago -> I can only say: soon ™️
In meantime, nightly is available.

@mduleone is using a patch a feasible option for you? I don't plan to backport this issue to any older version. Seemingly it has been there (the bug) for a long long time (unfortunately), and it is no regression introduced in any recent version.

@efstathiosntonas
Copy link
Copy Markdown

efstathiosntonas commented Apr 12, 2026

@kkafar thank you for the update. There's something off with the nightlies though? I see the latest one was submitted on npm 10 days ago, April 1st.

4.25.0-nightly-20260401-0636b922d

edit: yup, all failing: https://github.com/software-mansion/react-native-screens/actions/workflows/npm-screens-publish-nightly.yml

@kkafar
Copy link
Copy Markdown
Member

kkafar commented Apr 12, 2026

Indeed, I haven't noticed it during last week. Thanks. We'll sort it out on Monday.

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] ScreenDummyLayoutHelper leaks Activity due to unreleased view references and missing lifecycle cleanup

7 participants