Как освободить память, занимаемую изображениями в шаблоне данных в приложении Windows Phone 8?
У меня есть longlistselector, для которого у меня есть шаблон данных, который определяет тип элементов, которые будут добавлены в список. Шаблон данных имеет элемент управления Image, источник которого динамически связан с путем, поэтому каждый элемент в списке имеет связанный элемент управления Image. Проблема, с которой я сталкиваюсь, заключается в том, что эти средства управления изображениями никогда не освобождают память, которую они занимают, что приводит к исключению нехватки памяти. В обычном сценарии я устанавливаю bitmapImage.UriSource=null, чтобы освободить память, связанную с растровым изображением, но не могу найти способ сделать это в этом сценарии. Вот код xaml для longlistselector и связанный с ним шаблон данных.
Шаблон данных
<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" />
Я очень новичок в программировании Windows Phone. В основном я хочу развить опыт работы с изображениями в браузере. Пожалуйста, помогите мне с способами освободить память. В случае, если я делаю это совершенно неправильно, пожалуйста, исправьте меня или предложите лучшие способы достижения той же функциональности. Спасибо заранее...
3 ответа
Решение, которое я нашел для обработки этого случая, заключается в создании пользовательского элемента управления, чтобы автоматически установить для Urisource значение 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;
}
}
}
Затем просто оберните все ваши изображения в этот элемент управления:
<my:SafePicture>
<Image Source="{Binding Path=path}" />
</my:SafePicture>
При прокрутке с вашим кодом (без использования Loaded) изображения теряются после прокрутки вниз и возврата в верхнюю часть списка (скорость не имеет значения). При использовании Loaded прокрутка wokrs в порядке: можно прокрутить вниз и вернуться наверх (отладчик показывает, что вызываются Unloaded и Loaded), и изображения там. Однако при переходе на другую страницу (у меня есть страницы с основными данными), они перепутаны.
По умолчанию Windows Phone хранит сообщения, загруженные из Uri, в памяти, чтобы избежать необходимости загружать их снова. (Это грубая форма кеширования.)
Чтобы освободить память, используемую этими изображениями, вам необходимо явно освободить все ссылки на них. Посмотрите MSDN: Подсказки Изображения для Windows Phone 7 для получения дополнительной информации