maui
maui copied to clipboard
[Android] [Shell] replace navigation leaks current page
Description
Shell is leaking the page on android upon replace on Android.
- from a shell content
- push a page
GoToAsync("child")
- from the child, replace it
GoToAsync("../other-child")
- now check if
child
page is still alive
Steps to Reproduce
This is the UITest to prove the leak.
namespace Maui.Controls.Sample.Issues
{
[Issue(IssueTracker.Github, 99999, "Shell leaks when replacing a page", PlatformAffected.Android)]
public class Issue99999 : Shell
{
public Issue99999()
{
var mainContent = new ShellContent
{
ContentTemplate = new DataTemplate(() => new InitialPage()),
Title = "Initial",
Route = "initial"
};
Items.Add(mainContent);
Routing.RegisterRoute("Issue99999_child", typeof(ChildPage));
Routing.RegisterRoute("Issue99999_replace", typeof(ReplacePage));
}
}
file class InitialPage : ContentPage
{
public WeakReference<Page> ChildPageReference { get; set; }
public InitialPage()
{
Padding = 24;
Content = new Button
{
Text = "Go to child page",
AutomationId = "goToChildPage",
VerticalOptions = LayoutOptions.Start,
Command = new Command(() => Shell.Current.GoToAsync("Issue99999_child"))
};
}
}
file class ChildPage : ContentPage
{
public ChildPage()
{
Padding = 24;
Content = new Button
{
Text = "Replace",
AutomationId = "replace",
VerticalOptions = LayoutOptions.Start,
Command = new Command(() => Shell.Current.GoToAsync("../Issue99999_replace"))
};
}
protected override void OnParentSet()
{
base.OnParentSet();
if (Parent is ShellSection section)
{
var initialPage = (section.CurrentItem as IShellContentController).Page as InitialPage;
initialPage!.ChildPageReference = new WeakReference<Page>(this);
}
}
}
file class ReplacePage : ContentPage
{
public ReplacePage()
{
Padding = 24;
Button checkRefButton = null;
checkRefButton = new Button
{
Text = "Check reference",
AutomationId = "checkReference",
VerticalOptions = LayoutOptions.Start,
Command = new Command(async () =>
{
GC.Collect();
GC.WaitForPendingFinalizers();
await Task.Yield();
var section = (ShellSection)Parent;
var initialPage = (InitialPage)(section.CurrentItem as IShellContentController).Page;
checkRefButton.Text = initialPage.ChildPageReference.TryGetTarget(out var page) ? "alive" : "gone";
})
};
var backButton = new Button
{
Text = "Go back",
AutomationId = "goBack",
VerticalOptions = LayoutOptions.Start,
Command = new Command(() => Shell.Current.GoToAsync(".."))
};
Content = new VerticalStackLayout
{
checkRefButton,
backButton
};
}
}
}
Link to public reproduction project repository
No response
Version with bug
8.0.91 SR9.1
Is this a regression from previous behavior?
Not sure, did not test other versions
Last version that worked well
Unknown/Other
Affected platforms
Android
Affected platform versions
No response
Did you find any workaround?
Navigate back. Then push the new page. But obviously the user experience is impacted by that.
Relevant log output
No response