2

I have a LongListSelector which contains a image control which loads a lot of images from the web, this works fine for some time, but after i loaded some images i get out of memory exception. I read other people having the same issue regarding out of memory with a lot of images but still haven't found a solution. I have read that it has something to do with image/BitmapImage cache.

Here is my LongListSelector which contains the image control:

<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>

In my MainPage.xaml.cs i set the DataContext of my LongListSelector:

llsGameList.DataContext = gd.GetGamesListItems;

And here is the class i use to store my image in:

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

Here is the ObservableCollection containing all the images:

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

I hope i explained it clearly. I really hope there is someone that can help me fix this memory problem. Thanks.

Thunder
  • 117
  • 18
  • You can try this: http://stackoverflow.com/a/17495047/869621 – Kevin Gosse May 13 '14 at 15:52
  • @KooKiz Do the method remove the image memory cache problem completely ? – Thunder May 13 '14 at 16:10
  • @KooKiz ohh i see you wrote that it does not remove memory leak completely. Is there not a way to not leak any memory at all? – Thunder May 13 '14 at 16:18
  • None that I know of. But the trick takes care of what uses the bigger amount of memory: pictures. Memory used by control themselves is pretty much negligible – Kevin Gosse May 13 '14 at 17:19
  • Okay thanks. Can you show me how to implement it into my code, then i will i will mark you answer as accepted :). – Thunder May 13 '14 at 17:35

1 Answers1

5

I know no way to prevent the LongListSelector from leaking memory. However, you can use a small trick to free the memory used by pictures.

First, create a new class, called SafePicture, and make it inherit from ContentControl. Inside, implement the logic to free the memory used by the bitmap:

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;
        }
    }
}

Then, wrap all your pictures using this custom control:

<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>

Note that the namespace my refers to the assembly you've put the SafePicture in, and must be declared on top of your page:

xmlns:my="clr-namespace:yourNamespace"
Kevin Gosse
  • 38,392
  • 3
  • 78
  • 94
  • Thanks dude :). I will test this soon. Also have this fix worked for yourself ? when you used it in any of your apps?. – Thunder May 13 '14 at 18:23
  • Okay i implemented the code, but how shall i call the code?, is the code called automatically? – Thunder May 13 '14 at 19:21
  • @Thunder It is called automatically. You can set a breakpoint in the `SafePictureUnloaded` method if you have a doubt. And yes, I use it in my apps, it's the only reliable way I've found to deal with those memory leaks – Kevin Gosse May 13 '14 at 20:43
  • Okay, thanks again. I tested it now and i think it is reducing the memory usage :). But still the memory raises a little everytime, is it a bug in the LongListSelector that make this happen?. If i used a listbox control, do you think it would work better?. – Thunder May 13 '14 at 20:45
  • You wouldn't have the leak with the listbox, but you wouldn't have virtualization either, which would be a huge issue to display a large number of pictures. Telerik controls are free for a limited time, you should seize the opportunity: http://www.telerik.com/account/teched.aspx Their RadDataBoundListBox supports virtualization *and* doesn't leak memory – Kevin Gosse May 13 '14 at 21:16
  • If i get the Telerik controls via the link you posted, can i use the Telerik controls in a Windows Phone app which is not free, where users have to pay for it?. Also what happens when my Telerik license runs out, will my app using the controls not work anymore then?. – Thunder May 14 '14 at 06:38
  • @Thunder It's a one year license. You own the controls, you can use them in whatever application you want. After the license expires, you can still use the controls, but you lose access to updates and support – Kevin Gosse May 14 '14 at 08:15
  • Okay. I think im gonna use RadDataBoundListBox control then. Thanks again for your time spent helping, i appreciate it :). – Thunder May 14 '14 at 09:02
  • Do you know a good tutorial on the Telerik Jump List?, its a extended Databound Listbox that im using. – Thunder May 21 '14 at 17:15
  • Is this still a known issue in Windows Phone 8.1 (Silverlight)? – Jedidja Sep 23 '14 at 00:06
  • @Jedidja Can't say for sure, but since Microsoft is encouraging developers to switch to WinRT, I doubt they'll fix this kind of issue – Kevin Gosse Sep 23 '14 at 20:46
  • It's a shame you still have to write in Silverlight if you want to be able to set the lock screen background (among other things) – Jedidja Sep 24 '14 at 14:38