草庐IT

c# - 内存泄漏处理 Xamarin.Forms

coder 2023-12-21 原文

我使用 Xamarin.Forms 创建的应用程序存在内存泄漏问题。我的应用程序由带图像的 ListView 组成。如果我单击一个项目并返回到 ListPage,我可以在我的输出窗口中看到内存占用。我尝试在我的 ContentPage 的 OnDisappearing() 中调用 GC.Collect()

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

文章列表页面.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>

关于c# - 内存泄漏处理 Xamarin.Forms,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29530253/

有关c# - 内存泄漏处理 Xamarin.Forms的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  3. ruby-on-rails - Ruby 中的内存模型 - 2

    ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序

  4. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  5. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  6. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  7. 键删除后 ruby​​ 哈希内存泄漏 - 2

    你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p

  8. Ruby-vips 图像处理库。有什么好的使用示例吗? - 2

    我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby​​代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby​​-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby​​-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby​​-vips的github页面上的链接,我们将不胜感激!如果有ruby​​-

  9. ruby - Faye WebSocket,关闭处理程序被触发后重新连接到套接字 - 2

    我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d

  10. ruby - 如何使用 Ruby HTTP::Net 处理 404 错误? - 2

    我正在尝试解析网页,但有时会收到404错误。这是我用来获取网页的代码:result=Net::HTTP::getURI.parse(URI.escape(url))如何测试result是否为404错误代码? 最佳答案 像这样重写你的代码:uri=URI.parse(url)result=Net::HTTP.start(uri.host,uri.port){|http|http.get(uri.path)}putsresult.codeputsresult.body这将打印状态码和正文。

随机推荐