内存泄漏处理Xamarin.Forms [英] Memory leak handling Xamarin.Forms

查看:93
本文介绍了内存泄漏处理Xamarin.Forms的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Xamarin.Forms创建的应用程序中存在内存泄漏问题.我的应用程序包含一个带图片的ListView.如果单击某个项目并返回到ListPage,则可以在输出"窗口中看到内存消耗.我尝试在ContentPage的OnDisappearing()中调用GC.Collect().

I have a memory leak issue in my application which I have created with Xamarin.Forms. My app consists of A ListView with Images. If I click on an item and come back to the ListPage I can see a memory hog in my Output window. I have tried calling GC.Collect() in OnDisappearing() of my ContentPage.

我在Android项目中看到了base.Dispose().但是我不知道如何使用它.

I have seen a base.Dispose() in my Android project. But I don't know how to use it.

ArticleListPage.xaml

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>

推荐答案

我前一段时间遇到此问题,并且

I had this problem a while back and this article solved it for me. Basically you need to make a custom Renderer and place that in your droid project:

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中或您的页面所在的任何位置.

Then Extend the Image class and place that in the PCL, or wherever your pages reside.

namespace ApplicationClient.CustomControls
{
    public class LSImage : Image
    {
    }
}

然后,您必须修改XAML才能与此一起使用.

Then you have to modify the XAML to work with this as well.

<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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆