Windows phone 8 Изображения внутри утечки памяти LongListSelector

У меня есть LongListSelector, который содержит элемент управления изображением, который загружает много изображений из Интернета, некоторое время это работает нормально, но после того, как я загрузил некоторые изображения, я получаю исключение из памяти. Я читал других людей, у которых была такая же проблема с нехваткой памяти с большим количеством изображений, но до сих пор не нашел решения. Я читал, что это как-то связано с кешем изображений/BitmapImage.

Вот мой LongListSelector, который содержит элемент управления изображением:

<phone:Pivot Title="MY APPLICATION">
        <!--Pivot item one-->
        <phone:PivotItem Header="Browse">
            <Grid>
                <phone:LongListSelector Name="llsGameList" ItemsSource="{Binding}" Tap="llsGameList_Tap" Margin="0,90,0,0">
                    <phone:LongListSelector.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                    <Image Name="imgGameList" Margin="0,10,0,10" Stretch="Fill" HorizontalAlignment="Left" VerticalAlignment="Top" Height="200" Width="150">
                                        <Image.Source>
                                            <BitmapImage UriSource="{Binding BoxArtFrontThumb}"
                                 CreateOptions="BackgroundCreation" DecodePixelHeight="200" DecodePixelWidth="150" />
                                        </Image.Source>
                                    </Image>
                            </Grid>
                        </DataTemplate>
                    </phone:LongListSelector.ItemTemplate>
                </phone:LongListSelector>
            </Grid>
        </phone:PivotItem>

В моем MainPage.xaml.cs я установил DataContext моего LongListSelector:

llsGameList.DataContext = gd.GetGamesListItems;

И вот класс, который я использую для хранения своего изображения:

public class GetGamesList 
{
    public Uri BoxArtFrontThumb { get; set; }
}

Вот ObservableCollection, содержащий все изображения:

 private ObservableCollection<GetGamesList> _GetGamesListItems = new ObservableCollection<GetGamesList>();
    public ObservableCollection<GetGamesList> GetGamesListItems
    {
        get
        {
            return this._GetGamesListItems;
        }
    }

Надеюсь понятно объяснил. Я действительно надеюсь, что есть кто-то, кто может помочь мне решить эту проблему с памятью. Спасибо.


person Thunder    schedule 13.05.2014    source источник
comment
Вы можете попробовать это: stackoverflow.com/a/17495047/869621   -  person Kevin Gosse    schedule 13.05.2014
comment
@KooKiz Устраняет ли этот метод проблему с кешем памяти изображений полностью?   -  person Thunder    schedule 13.05.2014
comment
@KooKiz, ооо, я вижу, вы написали, что это не устраняет утечку памяти полностью. Есть ли способ вообще не утекать память?   -  person Thunder    schedule 13.05.2014
comment
Ни один, о котором я знаю. Но хитрость касается того, что использует больший объем памяти: изображений. Память, используемая самим элементом управления, практически незначительна   -  person Kevin Gosse    schedule 13.05.2014
comment
Хорошо спасибо. Можете ли вы показать мне, как реализовать это в моем коде, тогда я отмечу ваш ответ как принятый :).   -  person Thunder    schedule 13.05.2014


Ответы (1)


Я не знаю способа предотвратить утечку памяти LongListSelector. Тем не менее, вы можете использовать небольшую хитрость, чтобы освободить память, используемую изображениями.

Сначала создайте новый класс с именем SafePicture и сделайте его наследником ContentControl. Внутри реализуйте логику для освобождения памяти, используемой растровым изображением:

public class SafePicture : System.Windows.Controls.ContentControl
{
    public SafePicture()
    {
        this.Unloaded += this.SafePictureUnloaded;
    }

    private void SafePictureUnloaded(object sender, System.Windows.RoutedEventArgs e)
    {
        var image = this.Content as System.Windows.Controls.Image;

        if (image != null)
        {
            image.Source = null;
        }
    }
}

Затем оберните все ваши изображения, используя этот пользовательский элемент управления:

<phone:Pivot Title="MY APPLICATION">
    <!--Pivot item one-->
    <phone:PivotItem Header="Browse">
        <Grid>
            <phone:LongListSelector Name="llsGameList" ItemsSource="{Binding}" Tap="llsGameList_Tap" Margin="0,90,0,0">
                <phone:LongListSelector.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <my:SafePicture>
                                <Image Name="imgGameList" Margin="0,10,0,10" Stretch="Fill" HorizontalAlignment="Left" VerticalAlignment="Top" Height="200" Width="150">
                                    <Image.Source>
                                        <BitmapImage UriSource="{Binding BoxArtFrontThumb}"
                             CreateOptions="BackgroundCreation" DecodePixelHeight="200" DecodePixelWidth="150" />
                                    </Image.Source>
                                </Image>
                            </my:SafePicture>
                        </Grid>
                    </DataTemplate>
                </phone:LongListSelector.ItemTemplate>
            </phone:LongListSelector>
        </Grid>
    </phone:PivotItem>

Обратите внимание, что пространство имен my относится к сборке, в которую вы поместили SafePicture, и должно быть объявлено вверху вашей страницы:

xmlns:my="clr-namespace:yourNamespace"
person Kevin Gosse    schedule 13.05.2014
comment
Спасибо чувак :). Я проверю это в ближайшее время. Также сработало ли это исправление для вас? когда вы использовали его в любом из ваших приложений?. - person Thunder; 13.05.2014
comment
Хорошо, я реализовал код, но как мне вызвать код? Код вызывается автоматически? - person Thunder; 13.05.2014
comment
@Thunder Вызывается автоматически. Вы можете установить точку останова в методе SafePictureUnloaded, если у вас есть сомнения. И да, я использую его в своих приложениях, это единственный надежный способ справиться с этими утечками памяти. - person Kevin Gosse; 14.05.2014
comment
Хорошо, еще раз спасибо. Я проверил это сейчас, и я думаю, что это уменьшает использование памяти :). Но все же память немного увеличивается каждый раз, это ошибка в LongListSelector, из-за которой это происходит? Как вы думаете, если бы я использовал элемент управления списком, он работал бы лучше? - person Thunder; 14.05.2014
comment
У вас не будет утечки со списком, но у вас также не будет виртуализации, которая будет огромной проблемой для отображения большого количества изображений. Элементы управления Telerik бесплатны в течение ограниченного времени, вы должны воспользоваться этой возможностью: telerik.com/account/teched .aspx Их RadDataBoundListBox поддерживает виртуализацию и не допускает утечки памяти - person Kevin Gosse; 14.05.2014
comment
Если я получу элементы управления Telerik по ссылке, которую вы разместили, могу ли я использовать элементы управления Telerik в приложении для Windows Phone, которое не является бесплатным, где пользователи должны платить за это? Кроме того, что произойдет, когда моя лицензия Telerik закончится, мое приложение, использующее элементы управления, больше не будет работать? - person Thunder; 14.05.2014
comment
@Thunder Это лицензия на один год. Вы владеете элементами управления, вы можете использовать их в любом приложении. По истечении срока действия лицензии вы по-прежнему можете использовать элементы управления, но теряете доступ к обновлениям и поддержке. - person Kevin Gosse; 14.05.2014
comment
Хорошо. Я думаю, что тогда я буду использовать элемент управления RadDataBoundListBox. Еще раз спасибо за ваше время, потраченное на помощь, я ценю это :). - person Thunder; 14.05.2014
comment
Знаете ли вы хороший учебник по списку переходов Telerik? Это расширенный список с привязкой к данным, который я использую. - person Thunder; 21.05.2014
comment
Это все еще известная проблема в Windows Phone 8.1 (Silverlight)? - person Jedidja; 23.09.2014
comment
@Jedidja Не могу сказать наверняка, но поскольку Microsoft поощряет разработчиков переходить на WinRT, я сомневаюсь, что они исправят эту проблему. - person Kevin Gosse; 24.09.2014
comment
Жаль, что вам все еще нужно писать в Silverlight, если вы хотите установить фон экрана блокировки (среди прочего) - person Jedidja; 24.09.2014