我花了很多时间试图在 Android 上的 Xamarin.Forms 应用程序中追踪内存泄漏。经过很多死胡同和虚假的黎明之后,我想我可能遇到了导致问题的原因。
使用 Xamarin Profiler,我可以看到,只要我创建了一个样式并将其应用于控件(或者实际上只是一个隐式样式),我们就会得到多个保持“实时”的弱引用 - 即没有被垃圾收集。
请注意,我假设它们引用的对象已被 GC 处理(因为对对象的引用很弱),但 WeakReferences 本身仍然存在。
现在当然 WeakReferences 很小,我知道 - 但是当你在页面推送/弹出的每次迭代中创建数百个时,内存加起来就会出现严重泄漏。
这是详细信息。
使用 Xamarin.Forms 2.3.4.270(我们还没有升级,因为我们想保留已知问题!)
在 Android 上运行 - 物理设备。
应用程序.xaml:
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:ProfiledFormsApp2;assembly=ProfiledFormsApp2"
x:Class="ProfiledFormsApp2.App">
<Application.Resources>
<ResourceDictionary>
<Style TargetType="Label">
<Setter Property="FontSize" Value="Large" />
<Setter Property="TextColor" Value="Blue" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
页面 XAML:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage Title="Plain Page" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="ProfiledFormsApp2.PlainPage">
<ContentPage.Content>
<StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Core Navigation"/>
<Label Text="Number of items:" />
<Label Text="{Binding ItemsCount}" />
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
当我导航到上述页面并返回 3 次时,我们创建了以下 WeakReference(和相关)类 - 下面的屏幕截图来自 Profiler 快照。
请注意,我们有 55 个弱引用。深入了解这些节目:
有趣的是,这些 WeakReferences 似乎是作为 Behavior 和 Trigger 附加的一部分创建的。查看顶部的调用树给出:
因此,似乎 WeakReference 是作为设置 BindableObject 的值和样式的后续设置的一部分而创建的。
而且似乎 WeakReference 仍在内存中并被某些东西引用 - 行为集合?
使用 Profiler,我可以看到我们没有剩余未 GC 的标签。它似乎是主题/行为/触发器处理中的东西。
我还没有查看 GitHub 上的 Xamarin.Forms 代码 - 这可能是我的下一步行动。
有没有人观察到这一点或得到了解决方案?
最佳答案
我不确定控件的隐式样式,但对于显式样式,您可以在页面超出范围或消失时删除它们。
例如,我们将显式样式应用于按钮
<Button x:Name="btnSave" Style="{StaticResource SaveButtonStyle}" Content="Save"/>
protected override void OnDisappearing()
{
btnSave.Style = null;
base.OnDisappearing();
}
触发器和行为也可以这样做(您可以清除它们)。
我认为对于隐式样式,只有框架代码中有一些东西。我们无法确定如何将默认控件样式附加到默认控件。
关于memory-leaks - Xamarin.Forms 样式导致 WeakReference 泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48081601/