memory-leaks - Xamarin.Forms 样式导致 WeakReference 泄漏

标签 memory-leaks xamarin.forms weak-references xamarin.forms-styles

我花了很多时间试图在 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/

相关文章:

c++ - Valgrind 提示内存泄漏,但我正在调用 new 和 delete

ios - Xamarin.Forms 如何在 Android 和 iOS 上添加应用评​​分?

ios - 作为iVar的weakSelf

java - 将大型二进制文件读入内存后如何清理

swift - 惰性初始化和保留周期

c# - 在不知道谁是父级的情况下从父级中删除 View

xamarin.forms - Xamarin 表单的 Numericupdown 控件

java - 如何在 Java 中为 ReferenceQueue.remove() 指定正确的类型?

objective-c - 嵌套 block 和对自身的引用

node.js - 内存泄漏 Meteor.http