How to free memory hold by images in data template in windows phone 8 App?
Asked Answered
S

3

2

I have a longlistselector for which I have a data template that defines the type of items to be added to the list. The data template has an Image control whose source is binded with path dynamically, thus each item in list has an associated Image Control. The problem I face is that these Image control never free the memory they occcupy resulting in out of memory exception. On normal scenario I set bitmapImage.UriSource=null to deallocate the memory associated with the bitmap But can't find a way to do so in this scenario. Here is the xaml code for the longlistselector and the data template associated with it..

Data Template

<phone:PhoneApplicationPage.Resources>
    <DataTemplate x:Key="MediaItemTemplate">      
        <Canvas VerticalAlignment="Top">
            <Border BorderBrush="#FF4791CA" BorderThickness="3">
                <Image Height="100" Width="100" VerticalAlignment="Top" Grid.RowSpan="2" Stretch="UniformToFill">
                    <Image.Source> 
                          <BitmapImage UriSource="{Binding path}" CreateOptions="BackgroundCreation"  DecodePixelHeight="50" DecodePixelWidth="50"/>
                    </Image.Source>
                </Image>
             </Border>
             <Image Source="/Icons/check.png" Height="16" Width="16" Grid.Row="0" Grid.Column="0" VerticalAlignment="Top" Margin="80,7,7,0" Canvas.ZIndex="100" OpacityMask="Black" Visibility="{Binding visibility}" Name="checkImage" >    
             </Image>
          </Canvas> 
      </DataTemplate>
</phone:PhoneApplicationPage.Resources>

LonglistSelector

<phone:LongListSelector 
            Tap="ListMedia_Tap"
            x:Name="ListMedia"
            HorizontalAlignment="Left"
            Height="624" 
            VerticalAlignment="Top"
            Width="436"

Background="Transparent"

ItemTemplate="{StaticResource MediaItemTemplate}" LayoutMode="Grid" GridCellSize="120,120"/>

I am very new to windows phone programming, What basically I want to do is to develop kind of image browser experience. Please Help me out with ways to deallocate the memory. In case I am doing it completely wrong please correct me or suggest better ways to achieve the same functionality. Thanx in advance...

Spud answered 10/7, 2013 at 13:24 Comment(0)
U
2

A solution I've found to handle this case is making a custom control to automatically set the urisource to null:

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, just wrap all your pictures in that control:

<my:SafePicture>
    <Image Source="{Binding Path=path}" />
</my:SafePicture>
Unexampled answered 10/7, 2013 at 14:18 Comment(8)
Wow, sounds like a plan.Aude
Though, its not working for virtualization: when item are loaded again, they are empty. I tried to store image in the private field, that seems to work, but images are mixed up randomly somehow.Aude
but images are mixed up randomly somehow Probably a concurrency issue. Loading a picture is asynchronous, if you ask the Image control to load two pictures in succession, the second one can finish before the first one, and at the end it will be the first one that is displayedUnexampled
But image is set as private field. Or, maybe i should store image id as private, and then request loader/cacher to get image with that id?Aude
@VitaliiVasylenko It's hard to tell without seeing your implementation. Actually, I'm not even sure why you end up with empty images, I don't remember having the same issue. I'll try to reproduce it when I have some time.Unexampled
Ah, i forgot to share updated code. So, i'll try to formulate the problem from the very beginning. If i'm trying to use your code, i'm ending up with empty images (because of virtualization, Unloaded is rised for unsused items, and they cant get their data back, when they are needed again). So, i added storing image data into private field: pastebin.com/MNHkfAwt In this case, images are restoring, but mixed up randomly.Aude
and they cant get their data back, when they are needed again The key of the problem is understanding why they can't get their data back. Unfortunately I can't debug it right now, but I see two possibilities: either a concurrency issue (does the issue occur only when scrolling quickly, or also when scrolling slowly?), or maybe the code is overwriting the binding by setting explicitly the source. One solution could be to declare a Source dependency property on the SafePicture, and bind that property in the XAML. Then, in the SafePicture, update the source of the child Image accordinglyUnexampled
Hi, i added dependency property, but problem is pretty the same: links are mixed up. #19136660Aude
L
0

By default Windows Phone stores messages downloaded from a Uri in memory to save having to load them again. (It's a crude form of caching.)

To free the memory used by these images you needed to explicitly free all references to them. See MSDN: Image Tips for Windows Phone 7 for more details

Legible answered 10/7, 2013 at 13:38 Comment(0)
A
0

When scrolling with your code (without using Loaded), then images are lost after scrolling down and returning to the top of the list (speed no matter). While using Loaded, scrolling wokrs okay: it is possible to scroll down and return to the top, (debugger shows that Unloaded and Loaded are called), and images are there. However, when moving to another page (i have master-detail pages), they are mixed up.

Aude answered 20/9, 2013 at 10:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.