Skip to content

[net11.0][Android] Fix StackNavigationManager binary break and ShellItemWrapperFragment OnDestroyView gap (follow-up #34758) - #36133

Merged
kubaflo merged 9 commits into
dotnet:net11.0from
Vignesh-SF3580:fix-followup34758
Jul 26, 2026
Merged

[net11.0][Android] Fix StackNavigationManager binary break and ShellItemWrapperFragment OnDestroyView gap (follow-up #34758)#36133
kubaflo merged 9 commits into
dotnet:net11.0from
Vignesh-SF3580:fix-followup34758

Conversation

@Vignesh-SF3580

Copy link
Copy Markdown
Contributor

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Issue Details

PR #34758 introduced the Android handler-based Shell architecture. During review, two follow-up issues were identified and tracked in issue #36108:
Concern 1 — StackNavigationManager.Connect(IView) binary compatibility
Connect(IView) was a shipped public API. PR #34758 replaced it with a 2-parameter overload using an optional parameter. Although source-compatible, it is binary-breaking because existing precompiled callers may fail with MissingMethodException at runtime.
Concern 2 — ShellItemWrapperFragment missing OnDestroyView
ShellItemWrapperFragment did not override OnDestroyView. If the view is destroyed while the fragment remains alive (back-stack scenario), _viewPager and _rootLayout can retain detached views, causing memory leaks. View recreation can also skip adapter setup, resulting in a blank screen.

Root Cause

Concern 1: Optional parameter overloads are source-compatible but not binary-compatible. Existing compiled callers referencing Connect(IView) cannot resolve the new 2-parameter signature at runtime.

Concern 2: Android fragments separate view destruction (OnDestroyView) from fragment destruction (Dispose). Without OnDestroyView, view references remain held when the fragment stays on the back stack.

Description of Changes

Fix 1 — StackNavigationManager.cs: Added the 1-arg Connect(IView) overload that delegates to Connect(IView, null), restoring the original binary-compatible API. Removed the duplicate entry from Core/PublicAPI.Unshipped.txt since it already exists in PublicAPI.Shipped.txt.

Fix 2 — ShellItemWrapperFragment.Android.cs: Added OnDestroyView() to clear _viewPager, _adapter, and _rootLayout references, preventing detached view leaks and allowing proper view recreation. Updated _adapter accessibility for fragment access and registered the API change in Controls/PublicAPI.Unshipped.txt.

Issues Fixed

Fixes #36108

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 36133

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 36133"

@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Jun 25, 2026
@Vignesh-SF3580 Vignesh-SF3580 added the community ✨ Community Contribution label Jun 25, 2026
@github-actions github-actions Bot added area-controls-shell Shell Navigation, Routes, Tabs, Flyout platform/android labels Jun 25, 2026
@sheiksyedm
sheiksyedm marked this pull request as ready for review June 25, 2026 13:57
@sheiksyedm sheiksyedm linked an issue Jun 25, 2026 that may be closed by this pull request
@kubaflo

This comment has been minimized.

@github-actions github-actions Bot added the s/agent-review-in-progress AI review is currently running for this PR label Jun 25, 2026
@kubaflo

This comment has been minimized.

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Expert Review — 4 findings

See inline comments for details.

@MauiBot MauiBot added s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Jun 25, 2026
@PureWeen PureWeen added the p/0 Current heighest priority issues that we are targeting for a release. label Jun 25, 2026

@PureWeen PureWeen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Adversarial multi-model review — 3 independent reviewers + dispute round

Methodology: Reviewer 1/2/3 (different model families) reviewed the diff independently, then a follow-up dispute round adjudicated single-reviewer findings against verified source. CI status is intentionally out of scope here.

✅ Fix 1 (StackNavigationManager binary compat) — verified correct

  • Connect(IView) (1-arg) exists in PublicAPI.Shipped.txt (line 3677), so removing the *REMOVED* line from Unshipped.txt and re-adding the overload in code is correct — RS0016/RS0017 will pass.
  • Git history confirms the pre-#34758 Connect(IView) body was equivalent to Connect(view, null) (container falls back to navigationView.Handler.PlatformView), so behavior is preserved.
  • Overload resolution: Connect(view) binds unambiguously to the exact-arity 1-arg overload — no source break (3/3 reviewers confirmed). The redundancy of a 1-arg overload alongside a 2-arg-with-optional-default was raised once and discarded — it is intentional and harmless for binary compat.

Fix 2 (OnDestroyView) — incomplete cleanup

OnDestroyView correctly nulls _viewPager/_adapter so the adapter rebinds, but the same back-stack re-setup path (OnViewCreated re-runs while the handler outlives the view) leaves sibling handler state stale. Independent reviewers confirmed at 3/3 the issues already flagged inline in the prior automated review:

  • _pageChangeCallback not resetSetupViewPagerAdapter's if (_pageChangeCallback is null) guard skips re-registration, so the new ViewPager2 never receives the page-change callback. Toolbar/top-tab sync silently breaks on back-stack return — a functional regression, not just a leak.
  • _rootLayout window-inset listener not removed before nulling — also defeats Dispose's own removal (it guards on _rootLayout is not null). Bounded by WeakReference pruning, but real.
  • _tabbedViewManager/_shellItemAdapter/_bottomNavigationView recreated without teardown in SetupTabbedViewManager.

This run additionally surfaced two issues not in the prior review (see inline comments):

  • Toolbar trackers + duplicate toolbar leak (3/3 after dispute)
  • Appearance observer double-registration (3/3 after dispute)

💡 Optional: _backPressedCallback is recreated in OnViewCreated but not nulled in OnDestroyView (only Dispose disposes it). Immaterial — it is auto-removed via ViewLifecycleOwner — but a one-line Dispose here would be symmetric.

Recommendation

The cleanest fix is an internal helper on ShellItemHandler (e.g. OnFragmentViewDestroyed()) that mirrors the DisconnectHandler teardown for the back-stack case: unregister+null _pageChangeCallback; dispose+null _toolbarTracker/_toolbarAppearanceTracker and remove _toolbar from _appBarLayout; tear down _tabbedViewManager/_shellItemAdapter; call RemoveAppearanceObserver; then null _viewPager/_adapter/_bottomNavigationView. OnDestroyView calls that helper and removes the _rootLayout inset listener. A device test exercising push → back on a Shell with bottom tabs (verify tab switching and toolbar appearance re-sync after the round-trip) would lock this down and catch the _pageChangeCallback regression.

Verdict: COMMENT — 3 independent reviewers with adversarial consensus. Fix 1 is solid; Fix 2 needs the cleanup above before merge.

MauiBot

This comment was marked as outdated.

@MauiBot MauiBot removed the s/agent-review-in-progress AI review is currently running for this PR label Jun 25, 2026
kubaflo added a commit that referenced this pull request Jun 25, 2026
… N real failures)

When the Android HostApp crashes mid-run (e.g. during a heavy category like
Shell), the test that was running fails in UITestBaseTearDown with 'The app was
expected to be running still, investigate as possible crash', and every
SUBSEQUENT fixture's OneTimeSetUp then times out waiting for 'Go To Test button'
(the app is dead / 'keeps stopping'). The result was a whole category rendered
as e.g. 'Shell 0/312 (312 ❌)' — looking like 312 real test failures when it was
one crash cascading.

The setup-failure classifier required 100% of a category's failures to match the
OneTimeSetUp/Go-To-Test signature; the 1-2 crash-teardown failures didn't match,
so the category fell back to 'N regular failures'. Now:
 - The matcher also recognizes the app-crash teardown signature
   ('investigate as possible crash' / UITestBase.UITestBaseTearDown), so the
   whole cascade is recognized as a single setup/infra event.
 - A new SetupFailureIsAppCrash flag distinguishes a crash from a pure
   navigation/fixture setup flake, and the crash entry is preferred as the
   representative sample so the rendered message shows the crash.
 - The renderer surfaces crashes CAUTIOUSLY and honestly: '⚠️ the HostApp
   crashed mid-run … an app crash can be an infrastructure flake OR a regression
   introduced by this PR — review the screenshots + logcat', instead of either
   'N ❌' (misleading) or 'infrastructure, not a PR failure' (which could hide a
   real regression). Genuine passes in other categories (e.g. Navigation 88/88)
   are unaffected and still shown.

Validated against the real PR #36133 deep artifact: Navigation stays 88/88
(SetupFailure=False); Shell -> SetupFailure=True, IsAppCrash=True; ViewBaseTests
-> SetupFailure=True, IsAppCrash=False (secondary cascade). Pester: 10/10.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Expert Review — 3 findings

See inline comments for details.

MauiBot

This comment was marked as outdated.

Copilot AI review requested due to automatic review settings June 26, 2026 10:47
Copilot AI review requested due to automatic review settings July 17, 2026 08:32

Copilot AI 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.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

@vishnumenon2684

Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests , maui-pr-devicetests

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 2 pipeline(s).

@Vignesh-SF3580

Copy link
Copy Markdown
Contributor Author

Could you please check if test failures are related?

@kubaflo I checked the CI test failures. My code changes are Android-specific, while the failing tests are on iOS and macOS. Therefore, these test failures are not related to my code changes.

@kubaflo

This comment has been minimized.

@github-actions github-actions Bot added the s/agent-review-in-progress AI review is currently running for this PR label Jul 24, 2026
@MauiBot

This comment has been minimized.

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

AI Review Summary

ℹ️ The review agent did not produce a full summary on this run (an infrastructure issue on the CI agent), but the deep UI tests completed — their results are below. Re-comment /review for a fresh full review.

Deep UI tests — 118 passed, 0 failed across 1 category on platform-pool agent (replaces in-process counts above). The deep UI run for 1 category (Shell) hit the per-category time budget, but because the app/emulator kept crashing — each retry failed to recover from an app crash (e.g. did not recover after crash-recovery attempts) and burned its whole slice until the deadline. This is an app-stability/infrastructure issue, not a time shortfall, so raising the budget will not help (it would just spin longer). Re-run the review to try again; if it recurs, check the build-output.log + logcat in the drop-deep-uitests artifact for the app-startup crash.

🧪 UI Test Execution Results (deep, platform pool)

Category Tests Snapshot diffs
ViewBaseTests 118/119 ✓
📎 Download drop-deep-uitests artifact (TRX + snapshot diffs)

@MauiBot MauiBot removed the s/agent-review-in-progress AI review is currently running for this PR label Jul 24, 2026
@kubaflo
kubaflo merged commit b85fe53 into dotnet:net11.0 Jul 26, 2026
130 of 141 checks passed
@github-actions github-actions Bot added this to the .NET 11.0-preview7 milestone Jul 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-controls-shell Shell Navigation, Routes, Tabs, Flyout community ✨ Community Contribution p/0 Current heighest priority issues that we are targeting for a release. partner/syncfusion Issues / PR's with Syncfusion collaboration platform/android s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Android Shell handler — post-merge follow-ups (from #34758)

7 participants