Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.

[Android] Fix content pages not Garbage collected #14717

Merged
merged 3 commits into from
Jan 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
using System;
using System.Threading;
using System.Threading.Tasks;

#if UITEST
using Xamarin.Forms.Core.UITests;
using Xamarin.UITest;
using NUnit.Framework;
#endif

namespace Xamarin.Forms.Controls.Issues
{
#if UITEST
[Category(UITestCategories.Github10000)]
[Category(UITestCategories.Shell)]
[Category(UITestCategories.TitleView)]
#endif
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 14657, "Shell pages are not released from memory", PlatformAffected.Android)]
public class Issue14657 : TestShell
{
static int pageCount = 0;
protected override void Init()
{
Routing.RegisterRoute(nameof(Issue14657_ChildPage), typeof(Issue14657_ChildPage));

var rootPage = CreateRootPage();

AddContentPage(rootPage);
}

ContentPage CreateRootPage()
{
var rootPage = CreateContentPage("Home page");
rootPage.Content = new StackLayout()
{
Children =
{
new Button()
{
Command = new Command(CollectMemory),
Text = "Force GC",
AutomationId = "GC_14657"
},
new Button()
{
Command = new Command(async () => await GoToChild()),
Text = "Go to child page",
AutomationId = "GoToChild_14657"
}
}
};
Shell.SetTitleView(rootPage, new StackLayout()
{
Orientation = StackOrientation.Horizontal,
Children = { new Label { Text = "Root Page" } }
});

return rootPage;
}

public class Issue14657_ChildPage : ContentPage
{
public Issue14657_ChildPage()
{
Interlocked.Increment(ref pageCount);

Content = new StackLayout
{
Children =
{
new Label()
{
Text = $"{pageCount}",
AutomationId = "CountLabel",
TextColor = Color.Black
},
new Button()
{
Command = new Command(CollectMemory),
Text = "Force GC",
AutomationId = "GC_14657"
}
}
};
}

~Issue14657_ChildPage()
{
Interlocked.Decrement(ref pageCount);
}
}

async Task GoToChild()
{
await GoToAsync(nameof(Issue14657_ChildPage));
}

static void CollectMemory()
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.WaitForPendingFinalizers();
GC.Collect();
}

#if UITEST
[Test]
public void Issue14657Test()
{
RunningApp.Tap("GoToChild_14657");
RunningApp.WaitForFirstElement("CountLabel")
.AssertHasText("1");
RunningApp.NavigateBack();
RunningApp.Tap("GC_14657");

RunningApp.Tap("GoToChild_14657");
RunningApp.WaitForFirstElement("CountLabel")
.AssertHasText("1");
RunningApp.NavigateBack();
RunningApp.Tap("GC_14657");

RunningApp.Tap("GoToChild_14657");
RunningApp.WaitForFirstElement("CountLabel")
.AssertHasText("1");
RunningApp.NavigateBack();
}

#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,7 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Issue14544.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue14657.cs" />
<Compile Include="$(MSBuildThisFileDirectory)_TemplateMarkup.xaml.cs">
<DependentUpon>_TemplateMarkup.xaml</DependentUpon>
<SubType>Code</SubType>
Expand Down
1 change: 1 addition & 0 deletions Xamarin.Forms.Platform.Android/Renderers/ContainerView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ protected override void Dispose(bool disposing)

if (disposing)
{
RemoveAllViews();
_shellViewRenderer?.TearDown();
_view = null;
}
Expand Down
14 changes: 13 additions & 1 deletion Xamarin.Forms.Platform.Android/Renderers/ShellContentFragment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,15 @@ public override AView OnCreateView(LayoutInflater inflater, ViewGroup container,

void Destroy()
{
if (_page != null)
{
var titleView = Shell.GetTitleView(_page);
if (titleView != null)
{
Shell.SetTitleView(_page, null);
}
}

((IShellController)_shellContext.Shell).RemoveAppearanceObserver(this);

if (_shellContent != null)
Expand All @@ -180,6 +189,8 @@ void Destroy()

if (_root is ViewGroup vg)
vg.RemoveView(_shellPageContainer);

_shellPageContainer.Dispose();
}

_renderer?.Dispose();
Expand All @@ -194,6 +205,7 @@ void Destroy()
_root = null;
_renderer = null;
_shellContent = null;
_shellPageContainer = null;
}

protected override void Dispose(bool disposing)
Expand Down Expand Up @@ -223,4 +235,4 @@ public override void OnDestroy()

protected virtual void SetAppearance(ShellAppearance appearance) => _appearanceTracker.SetAppearance(_toolbar, _toolbarTracker, appearance);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,10 @@ protected override void Dispose(bool disposing)
_currentMenuItems?.Clear();
_currentToolbarItems?.Clear();

_drawerLayout.RemoveDrawerListener(_drawerToggle);
_drawerToggle?.Dispose();

_toolbar.RemoveAllViews();
}

_currentMenuItems = null;
Expand Down