Skip to content
1 change: 1 addition & 0 deletions src/Controls/src/Core/FlyoutPage/FlyoutPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public Page Detail
{
previousDetail.SendNavigatedFrom(
new NavigatedFromEventArgs(destinationPage: value, NavigationType.Replace));
previousDetail.Handler?.DisconnectHandler();
Comment thread
pictos marked this conversation as resolved.
Outdated
}

_detail.SendNavigatedTo(new NavigatedToEventArgs(previousDetail, NavigationType.Replace));
Expand Down
48 changes: 48 additions & 0 deletions src/Controls/tests/DeviceTests/Memory/MemoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,11 @@ void SetupBuilder()
#if IOS || MACCATALYST
handlers.AddHandler<NavigationPage, NavigationRenderer>();
handlers.AddHandler<TabbedPage, TabbedRenderer>();
handlers.AddHandler<FlyoutPage, PhoneFlyoutPageRenderer>();
#else
handlers.AddHandler<NavigationPage, NavigationViewHandler>();
handlers.AddHandler<TabbedPage, TabbedViewHandler>();
handlers.AddHandler<FlyoutPage, FlyoutViewHandler>();
#endif
});
});
Expand Down Expand Up @@ -148,6 +150,52 @@ await CreateHandlerAndAddToWindow(new Window(navPage), async () =>
await AssertionExtensions.WaitForGC(references.ToArray());
}

#if ANDROID
[Fact("FlyoutPage Detail Navigation Does Not Leak")]
public async Task FlyoutPageDetailNavigationDoesNotLeak()
{
SetupBuilder();

var references = new List<WeakReference>();

var initialDetail = new NavigationPage(new ContentPage { Title = "Initial Detail" });

var flyoutPage = new FlyoutPage
{
Flyout = new ContentPage { Title = "Flyout" },
Detail = initialDetail
};
Comment thread
pictos marked this conversation as resolved.

await CreateHandlerAndAddToWindow(new Window(flyoutPage), async () =>
{
for (int i = 0; i < 4; i++)
{
var detailPage = new ContentPage
{
Title = $"Detail {i}",
Content = new Label { Text = $"Content {i}" }
};
var navPage = new NavigationPage(detailPage);

flyoutPage.Detail = navPage;
flyoutPage.IsPresented = false;

await OnLoadedAsync(detailPage);

references.Add(new(detailPage));
references.Add(new(navPage));
}
});


// The last page will be alive and attached to the FlyoutPage
references.RemoveAt(references.Count - 1);
references.RemoveAt(references.Count - 1);

await AssertionExtensions.WaitForGC(references.ToArray());
}
#endif

[Theory("Handler Does Not Leak")]
[InlineData(typeof(ActivityIndicator))]
[InlineData(typeof(Border))]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,11 @@ public override void OnResume()

public override void OnDestroy()
{
_fragmentContainerView?.RemoveView(_currentView);
_currentView?.RemoveFromParent();
Comment thread
pictos marked this conversation as resolved.
Outdated
_currentView = null;
_fragmentContainerView = null;
_navigationManager = null;

base.OnDestroy();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,10 @@ void SetNavHost(NavHostFragment? navHost)
return;

if (_navHost is MauiNavHostFragment oldHost)
{
oldHost.StackNavigationManager = null;
oldHost.Dispose();
Comment thread
pictos marked this conversation as resolved.
Outdated
}

if (navHost is MauiNavHostFragment newHost)
newHost.StackNavigationManager = this;
Expand Down
Loading