【问题标题】:lots of images sucking up memory and getting out of memory exception?大量图像占用内存并出现内存不足异常?
【发布时间】:2017-11-20 16:59:16
【问题描述】:

我遇到了不断增长的内存问题。有时几分钟后应用程序由于内存不足异常而崩溃。我从 SQL Server 数据库中检索图像,并从单独的类中的字节转换。

我的 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"
             x:Class="TestProject.Views.DetailViews.JsonDesertPage"
             xmlns:local ="clr-namespace:TestProject.Data">
    <ContentPage.Resources>
        <ResourceDictionary>
            <local:ByteArrayToImageConverter x:Key="severityTypeImageConvertertwo"/>
        </ResourceDictionary>
    </ContentPage.Resources>
    <ListView x:Name="listviewConactstwo" RowHeight="100" HorizontalOptions="FillAndExpand" HasUnevenRows="True" ItemSelected="listviewContacts_ItemSelected">
        <ActivityIndicator x:Name="ProgressLoadertwo" IsRunning="True"/>
        <ListView.ItemTemplate >
            <DataTemplate>
                <ViewCell>
                    <StackLayout  Orientation="Vertical" Padding="5">
                        <StackLayout Orientation="Horizontal"  BackgroundColor="Ivory" Opacity="0.9">
                            <Image Source="{Binding Image,Converter={StaticResource severityTypeImageConvertertwo}}" HeightRequest="120" WidthRequest="120"/>
                            <StackLayout Orientation="Vertical">
                                <Label Text="{Binding Name}" FontSize="Medium" TextColor="Gray" FontAttributes="Bold"/>
                                <BoxView HeightRequest="2" Margin="0,10,10,0" BackgroundColor="Gray" HorizontalOptions="FillAndExpand" />
                                <Label Text="{Binding Description}" FontSize="Micro" TextColor="Gray" FontAttributes="Bold"/>
                                <StackLayout Orientation="Horizontal" VerticalOptions="Start" HorizontalOptions="Start">
                                    <Label Text="$" FontSize="Micro" VerticalOptions="Start" HorizontalOptions="Start" TextColor="Gray" FontAttributes="Bold"/>
                                    <Label Text="{Binding Price}" FontSize="Micro" TextColor="Gray" FontAttributes="Bold"/>
                                </StackLayout>
                            </StackLayout>
                            <Image Source="arrowtwo.png" BackgroundColor="Transparent" WidthRequest="25" Margin="0,10,10,0"/>
                        </StackLayout>                        
                    </StackLayout>                    
                </ViewCell>                
            </DataTemplate>            
        </ListView.ItemTemplate>        
    </ListView>
</ContentPage>

我的代码:

using Newtonsoft.Json;
using Plugin.Connectivity;
using System;
using System.IO;
using System.Net.Http;
using TestProject.Data;
using TestProject.Models;
using Xamarin.Forms;

namespace TestProject.Views.DetailViews
{
    public partial class JsonDesertPage : ContentPage
    {
        public JsonDesertPage ()
        {
            InitializeComponent ();   

            this.BackgroundImage = "background.png";
            this.Title = "Soup Menu";
            GetJSON();
          //  CrossConnectivity.Current.ConnectivityChanged += Current_ConnectivityChanged;
        }


        protected async override void OnAppearing()
        {
            base.OnAppearing();

            if (!CrossConnectivity.Current.IsConnected)
            {
                await DisplayAlert("fail", "No Internet Connection.Offline Menu Activated", "Ok");
                await Navigation.PushAsync(new MainTabbed());
            }
            else
            {
                // await DisplayAlert("sucess", " Network Is Available.", "Ok");
                GetJSON();
            }
        }

        public async void GetJSON()
        {                
            var client = new HttpClient();
            // var response = await client.GetAsync("http://192.168.43.226/GetContactsDesert.php");
            var response = await client.GetAsync(Constants.BaseUrlpos + "GetContactsDesert.php");    

            string contactsJson = response.Content.ReadAsStringAsync().Result;   
            ContectList ObjContactList = new ContectList();

            if (response.IsSuccessStatusCode)
            {                    
                ObjContactList = JsonConvert.DeserializeObject<ContectList>(contactsJson);
                listviewConactstwo.ItemsSource = ObjContactList.contacts;
            }

            else
            {
                var textReader = new JsonTextReader(new StringReader(contactsJson));
                dynamic responseJson = new JsonSerializer().Deserialize(textReader);
                contactsJson = "Deserialized JSON error message: " + responseJson.Message;
                await DisplayAlert("fail", "no Network Is Available.", "Ok");
            }

            ProgressLoadertwo.IsVisible = false;            

        }

        private void listviewContacts_ItemSelected(object sender, SelectedItemChangedEventArgs e)
        {
            var itemSelectedData = e.SelectedItem as Contactone;
            Navigation.PushAsync(new JsonDetailsPage(itemSelectedData.ID, itemSelectedData.Image, itemSelectedData.Name, itemSelectedData.Code, itemSelectedData.Description, itemSelectedData.Price,itemSelectedData.isservicecharge, itemSelectedData.CostPrice));

        }
    }
}

这是我正在使用的页面之一:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace TestProject.Data
{
    public class ByteArrayToImageConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            ImageSource retSource = null;
            if (value != null)
            {
                byte[] imageAsBytes = (byte[])value;
                // byte[] decodedByteArray = System.Convert.FromBase64String(Encoding.UTF8.GetString(imageAsBytes, 0, imageAsBytes.Length));
                // var stream = new MemoryStream(decodedByteArray);
                retSource = ImageSource.FromStream(() => new MemoryStream(imageAsBytes));
            }
            return retSource;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            //return null;
            throw new NotImplementedException();
        }

    }
}

当我运行配置文件时,我可以看到当我在页面之间移动时,再见 [] 正在增长。我尝试了 FFimageloading 选项,它似乎不支持字节数组图像转换器。

如何解决内存增长问题?

【问题讨论】:

    标签: c# arrays json xamarin cross-platform


    【解决方案1】:

    发现了一些东西。如果没有完整的运行,我无法确定哪些是你的头疼,但是......

    使用 HttpClient 作为单例。我已经通过 Xam 架构确认了单例使用最适合 Xam 以及其他所有内容。

    注意 IDiposable 对象。

    以下代码返回一个 HttpResponse 方法。 HttpResponseMessage 是 IDisposeable。将其包裹在“使用”中。

    StringReader 继承自 IDisposable 的 TextReader。包裹在“使用”中。

    动态类型不确定。最好也将其包装在 using 中。请参阅Do you need to dispose of objects and set them to null? 了解更多信息。

    HttpClient 的 PNP 指南 - https://github.com/mspnp/performance-optimization/blob/465514674354c8f833c73882f7405ac22c4fd437/ImproperInstantiation/docs/ImproperInstantiation.md

    PNP 好/坏 HttpClient 示例 - https://github.com/mspnp/performance-optimization/tree/465514674354c8f833c73882f7405ac22c4fd437/ImproperInstantiation

    您使用的 HttpClient 错误,它正在破坏您的软件 - http://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/

    看看这是否有帮助。

        private HttpClient m_httpClient = new HttpClient();
        private HttpClient MyHttpClient
        {
            get
            {
                if ( m_httpClient==null )
                {
                    m_httpClient = new HttpClient();
                }
                return m_httpClient;
            }
        }
        public async void GetJSON()
        {
            // var client = new HttpClient();
            var client = MyHttpClient;
    
            // var response = await client.GetAsync("http://192.168.43.226/GetContactsDesert.php");
            // var response = await client.GetAsync(Constants.BaseUrlpos + "GetContactsDesert.php");
            string contactsJson = string.Empty;
            using (HttpResponseMessage response = await client.GetAsync(Constants.BaseUrlpos + "GetContactsDesert.php"))
            { 
                contactsJson = response.Content.ReadAsStringAsync().Result;
            }
            ContectList ObjContactList = new ContectList();
    
            if (response.IsSuccessStatusCode)
            {
                ObjContactList = JsonConvert.DeserializeObject<ContectList>(contactsJson);
                listviewConactstwo.ItemsSource = ObjContactList.contacts;
            }
    
            else
            {
                using (var textReader = new JsonTextReader(new StringReader(contactsJson)) )
                {
                    using (dynamic responseJson = new JsonSerializer().Deserialize(textReader))
                    { 
                        contactsJson = "Deserialized JSON error message: " + responseJson.Message;
                    }
                    await DisplayAlert("fail", "no Network Is Available.", "Ok");
                }
            }
    
            ProgressLoadertwo.IsVisible = false;
        }
    

    【讨论】:

    • 非常感谢您的回答,但“if (response.IsSuccessStatusCode)”中显示错误,我试图纠正它但不可能,我可以向您展示 xamarin 分析器图像,如果您喜欢在图像加载到列表视图时堆栈 grw 的速率。据我了解加载图像中的堆栈增加未处理的原因。如果有办法在我导航到下一页时处理列表视图图像,这可能有助于摆脱保留预加载的图像,问题是我不知道该怎么做????
    • 发布一个我可以运行的简单复制到 GitHub,我会看看。
    • 我退出 github 新手,所以我已经上传了我的项目文件,如果您无法获取它,请告诉我在 github 中更改链接github.com/wpanduka/panPosSystem
    • 嗨乔,你有时间看看我上传的 GitHub 文件吗?请告诉我,非常感谢。
    猜你喜欢
    • 2016-09-02
    • 2011-06-18
    • 2015-02-19
    • 2016-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多