GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — fix(android): stop the FragmentManager driving fragments with a dead entry by edusperoni · Pull Request #11352 · NativeScript/NativeScript Conversation
Contributor
PR Checklist
What is the current behavior?A Note How the fragment gets stranded. Navigation only evicts fragments via Why it is fatal rather than a no-op. Every callback on that path either reported the condition through
This correlates strongly with memory pressure: the tighter memory gets, the more the OS destroys and recreates activities, which is what strands the fragments in the first place. It was reported from production with 300+ occurrences on low-RAM (4 GB) devices, mostly on resume after the app had been idle. What is the new behavior?The stale fragment is discarded instead of taking the app down, and it stops being stale in the first place:
Removals are always committed with Also considered and left out: extending the restored-fragment cleanup in No unit tests:
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions…entry A fragment can outlive the BackstackEntry it is bound to. Navigation only evicts fragments through transaction.replace(containerViewId, ...), so any fragment whose container no longer matches the frame's current container - left over from an activity recreation, a frame reset, or an interrupted navigation - stays added to the FragmentManager. _removeEntry then clears resolvedPage and drops entry.fragment without telling the FragmentManager, and the next transaction happily drives that fragment back through onCreateView. Every callback on that path either reported the condition with Trace.error - which routes to the error handler, rethrows, and becomes a fatal exception across the JNI boundary - or dereferenced the missing page directly, so the stale fragment took the app down instead of being discarded. - _removeEntry: detach the fragment's callbacks and remove it from the FragmentManager when it is still added, so it can neither be driven again nor resurrect the torn down page - findPageForFragment: discard an unclaimed restored fragment instead of throwing, and widen the entry lookup through _findEntryForTag so fragments restored from the backstack or the navigation queue are matched instead of treated as orphans - onDestroy: report a missing entry without throwing - onResume: bail out when the entry or page is gone rather than reading entry.resolvedPage.frame - onPause/onDestroyView: tolerate a missing frame
|
There was an error while loading. Please reload this page.
|
View your CI Pipeline Execution ↗ for commit f67ee37
💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗ ☁️ Nx Cloud last updated this comment at |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Prevents Android’s FragmentManager from driving orphaned fragments after their navigation entries are discarded.
Changes:
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
packages/core/ui/frame/index.android.ts |
Detaches and removes fragments for discarded entries. |
packages/core/ui/frame/frame-helper-for-android.ts |
Adds orphan cleanup and lifecycle guards. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| } else { | ||
| // Android also restores fragments that were only in the backstack or still queued, so | ||
| // widen the lookup before treating this fragment as an orphan. | ||
| entry = frame._findEntryForTag(fragmentTag); |
| Trace.write(`Could not find a page for ${fragmentTag}. Discarding orphaned fragment.`, Trace.categories.NativeLifecycle, Trace.messageType.error); | ||
| removeFragmentIfAdded(fragment); |
| callbacks.entry = null; | ||
| callbacks.frame = null; |
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.