【问题标题】:How to free memory hold by images in data template in windows phone 8 App?如何在 windows phone 8 App 中释放数据模板中图像的内存?
【发布时间】:2013-07-10 13:24:44
【问题描述】:

我有一个 longlistselector,我有一个数据模板,用于定义要添加到列表中的项目类型。数据模板有一个 Image 控件,其源与路径动态绑定,因此列表中的每个项目都有一个关联的 Image Control。我面临的问题是这些图像控件永远不会释放它们占用的内存,从而导致内存不足异常。在正常情况下,我设置 bitmapImage.UriSource=null 以释放与位图关联的内存但在这种情况下找不到这样做的方法。这是 longlistselector 的 xaml 代码和与之关联的数据模板..

数据模板

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

背景="透明"

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

我对windows phone 编程很陌生,基本上我想做的是开发一种图像浏览器体验。请帮助我解决分配内存的方法。如果我做错了,请纠正我或提出更好的方法来实现相同的功能。提前谢谢...

【问题讨论】:

    标签: windows-phone-8


    【解决方案1】:

    我发现处理这种情况的一个解决方案是制作一个自定义控件来自动将 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>
    

    【讨论】:

    • 哇,听起来像个计划。
    • 虽然,它不适用于虚拟化:再次加载项目时,它们是空的。我尝试将图像存储在私有字段中,这似乎可行,但是图像以某种方式随机混合。
    • but images are mixed up randomly somehow 可能是并发问题。加载图片是异步的,如果让Image控件连续加载两张图片,第二张可以在第一张之前完成,最后会显示第一张
    • 但是图像被设置为私有字段。或者,也许我应该将图像 id 存储为私有,然后请求 loader/cacher 以获取具有该 id 的图像?
    • @VitaliiVasylenko 没有看到你的实现很难说。实际上,我什至不确定你为什么会得到空图像,我不记得有同样的问题。有时间我会尝试重现它。
    【解决方案2】:

    默认情况下,Windows Phone 将从 Uri 下载的消息存储在内存中,以免再次加载它们。 (这是一种粗略的缓存形式。)

    要释放这些图像使用的内存,您需要显式释放对它们的所有引用。详情请见MSDN: Image Tips for Windows Phone 7

    【讨论】:

      【解决方案3】:

      使用代码滚动时(不使用 Loaded),向下滚动并返回列表顶部后图像会丢失(不管速度如何)。使用 Loaded 时,滚动工作正常:可以向下滚动并返回顶部,(调试器显示调用了 Unloaded 和 Loaded),并且图像在那里。但是,当移动到另一个页面(我有主从页面)时,它们会混淆。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-09-19
        • 1970-01-01
        • 2014-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多