内存泄漏处理Xamarin.Forms
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内存泄漏处理Xamarin.Forms相关的知识,希望对你有一定的参考价值。
我在我的应用程序中有一个内存泄漏问题,我用Xamarin.Forms创建。我的应用程序包含带有图像的ListView。如果我点击一个项目并返回到ListPage,我可以在“输出”窗口中看到内存耗尽。我试过在我的ContentPage的GC.Collect()
中调用OnDisappearing()
。
我在android项目中看到过base.Dispose()
。但我不知道如何使用它。
ArticleListPage.xaml
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:converters="clr-namespace:NewsArticles.Mobile.Converters;assembly=Something.NewsArticles.Mobile"
xmlns:themes="clr-namespace:NewsArticles.Mobile.Themes;assembly=Something.NewsArticles.Mobile"
x:Class="NewsArticles.Mobile.Pages.ArticlesListPage"
Title="{Binding PageTitle, Mode=OneWay}"
BackgroundColor="{x:Static themes:ColorResources.ArticleListPageBackgroundColor}">
<RelativeLayout>
<ContentPage.Resources>
<ResourceDictionary>
<converters:BooleanNegationConverter x:Key="booleanNegationConverter" />
<converters:StringToImageSourceConverter x:Key="stringToImageSourceConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<ListView x:Name="ArticlesList"
StyleId="ArticlesList"
Grid.Row="1"
IsVisible="{Binding IsProcessing, Mode=OneWay, Converter={StaticResource booleanNegationConverter}}">
<ListView.BackgroundColor>
<OnPlatform x:TypeArguments="Color" ios="Transparent" />
</ListView.BackgroundColor>
<ListView.RowHeight>
<OnPlatform x:TypeArguments="x:Int32" iOS="150" Android="180" WinPhone="170" />
</ListView.RowHeight>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ContentView BackgroundColor="{x:Static themes:ColorResources.ArticleListViewBackgroundColor}">
<ContentView.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="10,5"
Android="10,10"
WinPhone="10,10" />
</ContentView.Padding>
<Grid BackgroundColor="White" Padding="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0"
Source="{Binding ImageUrl, Mode=OneWay, Converter={StaticResource stringToImageSourceConverter}}"
HorizontalOptions="FillAndExpand"
Aspect="AspectFill" />
<Grid Grid.Column="1" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="20" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Text="{Binding Title, Mode=OneWay}"
VerticalOptions="Start"
LineBreakMode="WordWrap"
TextColor="{x:Static themes:ColorResources.MainArticleTitleColor}"
Font="{x:Static themes:FontResources.ListArticleTitle}" />
<ContentView Grid.Row="1" Padding="0,2">
<Label Text="{Binding Author, Mode=OneWay }"
TextColor="Silver"
Font="{x:Static themes:FontResources.VerySmall}" />
</ContentView>
<Label Grid.Row="2" Text="{Binding Body, Mode=OneWay}"
LineBreakMode="TailTruncation"
TextColor="Gray"
Font="{x:Static themes:FontResources.VerySmall}" />
</Grid>
</Grid>
</ContentView>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
答案
我有一段时间没有这个问题,this文章为我解决了这个问题。基本上你需要制作一个自定义渲染器并将其放在你的机器人项目中:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Views.InputMethods;
using Android.Widget;
using Android.Util;
using Application.Droid.CustomControls;
using ApplicationClient.CustomControls;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(ApplicationClient.CustomControls.LSImage), typeof(LSImageRenderer))]
namespace Application.Droid.CustomControls
{
public class LSImageRenderer : ImageRenderer
{
Page page;
NavigationPage navigPage;
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
if (GetContainingViewCell(e.NewElement) != null)
{
page = GetContainingPage(e.NewElement);
if (page.Parent is TabbedPage)
{
page.Disappearing += PageContainedInTabbedPageDisapearing;
return;
}
navigPage = GetContainingNavigationPage(page);
if (navigPage != null)
navigPage.Popped += OnPagePopped;
}
else if ((page = GetContainingTabbedPage(e.NewElement)) != null)
{
page.Disappearing += PageContainedInTabbedPageDisapearing;
}
}
}
void PageContainedInTabbedPageDisapearing (object sender, EventArgs e)
{
this.Dispose(true);
page.Disappearing -= PageContainedInTabbedPageDisapearing;
}
protected override void Dispose(bool disposing)
{
Log.Info("**** LSImageRenderer *****", "Image got disposed");
base.Dispose(disposing);
}
private void OnPagePopped(object s, NavigationEventArgs e)
{
if (e.Page == page)
{
this.Dispose(true);
navigPage.Popped -= OnPagePopped;
}
}
private Page GetContainingPage(Xamarin.Forms.Element element)
{
Element parentElement = element.ParentView;
if (typeof(Page).IsAssignableFrom(parentElement.GetType()))
return (Page)parentElement;
else
return GetContainingPage(parentElement);
}
private ViewCell GetContainingViewCell(Xamarin.Forms.Element element)
{
Element parentElement = element.Parent;
if (parentElement == null)
return null;
if (typeof(ViewCell).IsAssignableFrom(parentElement.GetType()))
return (ViewCell)parentElement;
else
return GetContainingViewCell(parentElement);
}
private TabbedPage GetContainingTabbedPage(Element element)
{
Element parentElement = element.Parent;
if (parentElement == null)
return null;
if (typeof(TabbedPage).IsAssignableFrom(parentElement.GetType()))
return (TabbedPage)parentElement;
else
return GetContainingTabbedPage(parentElement);
}
private NavigationPage GetContainingNavigationPage(Element element)
{
Element parentElement = element.Parent;
if (parentElement == null)
return null;
if (typeof(NavigationPage).IsAssignableFrom(parentElement.GetType()))
return (NavigationPage)parentElement;
else
return GetContainingNavigationPage(parentElement);
}
}
}
然后扩展Image
类并将其放在PCL中,或者放在页面所在的任何位置。
namespace ApplicationClient.CustomControls
{
public class LSImage : Image
{
}
}
然后你必须修改XAML才能使用它。
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ctrls="clr-namespace:ApplicationClient.CustomControls;assembly=ApplicationClient"
... >
<ctrls:LSImage ... />
</ContentPage>
以上是关于内存泄漏处理Xamarin.Forms的主要内容,如果未能解决你的问题,请参考以下文章
Xamarin Forms 在 UWP 上是不是存在内存泄漏?
Xamarin.Forms XAML的辅助功能Code Snippet
如何使用模块化代码片段中的LeakCanary检测内存泄漏?