对于前面一篇博客的补充-----显示大量圆形图片或头像时的内存优化做法
2015-06-14 21:33
113 查看
一般来说,我们还是比较习惯做成一个控件的,总不可能每次用到圆形图像的话,去写上面这么一大堆。下面我们就
来动手干!
在 Visual Studio 中新建一个用户控件(UserControl),我们命名为 CircleImage。
![](http://images0.cnblogs.com/blog/484187/201506/110818082547371.png)
然后在后台代码中定义一个依赖属性 Source,表示图片的源。由于 BitmapImage 的 UriSource 是 Uri 类型的,因
此我们的 Source 属性也是 Uri 类型。Source 变化时,我们设置到 XAML 中的 BitmapImage 的 UriSource 属性上
去。
然后开始编写前台 XAML:
将 BitmapImage 命名为 bitmapImage,给上面的后台 cs 代码使用。
这里可能你会奇怪,为什么我将解码的大小写成了 1?这是因为,如果解码大小写成小于 1 的整数的话,就等于没有
自动根据渲染大小来解码的功能了,那就跟一开始原文作者的效果一样。所以这里我先写成 1,运行的时候再根据控
件的大小来动态调整。
那么既然要动态调整,那么我们必须得完善后台代码了,添加一些代码上去,修改成这样:
这样我们就完成了这个控件了,接下来我们来测试下究竟这个东西威力有多大。
图片地址:http://images.cnblogs.com/cnblogs_com/h82258652/693238/o_wallpaper_summer2013_1920X1080.jpg
测试程序代码:
前台 XAML 代码:
都放在 GridView 里面,大小都设定为 100*100。
后台代码:
很简单,就是让 GridView 加载 100 个。
好,走起!
![](http://images0.cnblogs.com/blog/484187/201506/110818088946243.png)
初始运行占用 40.6 MB 内存,当然这个值可能下次运行就不一样了,多少会有点波动。
接下来我们加载旧版:
![](http://images0.cnblogs.com/blog/484187/201506/110818095821101.png)
令人吃惊,一瞬间就跑到 250.6 MB 内存了。
那我们再来看看新的版本,记得先将上面这个关掉,重新打开,否则影响结果。
新版:
![](http://images0.cnblogs.com/blog/484187/201506/110818103486999.png)
44.6 MB!基本没发生任何的变化。可见威力很强大,说明我们的代码起作用了。
个,但是仍然可以见到旧版的内存占用十分厉害, 所以根本没法想象真真正正加载 100 个的时候有多壮观。小小的
细节可能会引起巨大的变化,考虑到还有众多 512 MB 内存的 Windows Phone 用户,这点小小的细节仍然很有必
要去做的。
来动手干!
在 Visual Studio 中新建一个用户控件(UserControl),我们命名为 CircleImage。
![](http://images0.cnblogs.com/blog/484187/201506/110818082547371.png)
然后在后台代码中定义一个依赖属性 Source,表示图片的源。由于 BitmapImage 的 UriSource 是 Uri 类型的,因
此我们的 Source 属性也是 Uri 类型。Source 变化时,我们设置到 XAML 中的 BitmapImage 的 UriSource 属性上
去。
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(nameof(Source), typeof(Uri), typeof(CircleImage), new PropertyMetadata(null, SourceChanged)); private static void SourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var obj = (CircleImage)d; var value = (Uri)e.NewValue; obj.bitmapImage.UriSource = value; } public Uri Source { get { return (Uri)GetValue(SourceProperty); } set { SetValue(SourceProperty, value); } }
然后开始编写前台 XAML:
<UserControl x:Class="MyApp.CircleImage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:MyApp" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <Ellipse> <Ellipse.Fill> <ImageBrush> <ImageBrush.ImageSource> <BitmapImage x:Name="bitmapImage" DecodePixelWidth="1" DecodePixelHeight="1" /> </ImageBrush.ImageSource> </ImageBrush> </Ellipse.Fill> </Ellipse> </UserControl>
将 BitmapImage 命名为 bitmapImage,给上面的后台 cs 代码使用。
这里可能你会奇怪,为什么我将解码的大小写成了 1?这是因为,如果解码大小写成小于 1 的整数的话,就等于没有
自动根据渲染大小来解码的功能了,那就跟一开始原文作者的效果一样。所以这里我先写成 1,运行的时候再根据控
件的大小来动态调整。
那么既然要动态调整,那么我们必须得完善后台代码了,添加一些代码上去,修改成这样:
public sealed partial class CircleImage : UserControl { public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(nameof(Source), typeof(Uri), typeof(CircleImage), new PropertyMetadata(null, SourceChanged)); private static void SourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var obj = (CircleImage)d; var value = (Uri)e.NewValue; obj.bitmapImage.UriSource = value; } public Uri Source { get { return (Uri)GetValue(SourceProperty); } set { SetValue(SourceProperty, value); } } public CircleImage() { this.InitializeComponent(); this.SizeChanged += CircleImage_SizeChanged;// 监听控件大小发生变化。 } private void ReSize() { // 计算新的解码大小,向上取整。 int width = (int)Math.Ceiling(this.ActualWidth); int height = (int)Math.Ceiling(this.ActualHeight); // 确保解码大小必须大于 0,因为上面的结果可能为 0。 bitmapImage.DecodePixelWidth = Math.Max(width, 1); bitmapImage.DecodePixelHeight = Math.Max(height, 1); // 让 BitmapImage 重新渲染。 var temp = bitmapImage.UriSource; bitmapImage.UriSource = null; bitmapImage.UriSource = temp; } private void CircleImage_SizeChanged(object sender, SizeChangedEventArgs e) { ReSize(); } }
这样我们就完成了这个控件了,接下来我们来测试下究竟这个东西威力有多大。
测试:
测试图片使用我博客的背景图片,足够大的了,1920*1080,相信应该会吃掉不少内存^-^。图片地址:http://images.cnblogs.com/cnblogs_com/h82258652/693238/o_wallpaper_summer2013_1920X1080.jpg
测试程序代码:
前台 XAML 代码:
<Page x:Class="MyApp.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:MyApp" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <StackPanel Grid.Row="0" HorizontalAlignment="Center" Orientation="Horizontal"> <Button Content="加载旧版" Click="BtnOld_Click" /> <Button Content="加载新版" Click="BtnNew_Click" /> </StackPanel> <GridView Grid.Row="1" x:Name="gvwBigMemory"> <GridView.ItemTemplate> <DataTemplate> <Ellipse Width="100" Height="100"> <Ellipse.Fill> <ImageBrush ImageSource="http://images.cnblogs.com/cnblogs_com/h82258652/693238/o_wallpaper_summer2013_1920X1080.jpg" /> </Ellipse.Fill> </Ellipse> </DataTemplate> </GridView.ItemTemplate> </GridView> <GridView Grid.Row="2" x:Name="gvwMinMemory"> <GridView.ItemTemplate> <DataTemplate> <local:CircleImage Width="100" Height="100" Source="http://images.cnblogs.com/cnblogs_com/h82258652/693238/o_wallpaper_summer2013_1920X1080.jpg" /> </DataTemplate> </GridView.ItemTemplate> </GridView> </Grid> </Page>
都放在 GridView 里面,大小都设定为 100*100。
后台代码:
public sealed partial class MainPage : Page { public MainPage() { this.InitializeComponent(); } private void BtnOld_Click(object sender, RoutedEventArgs e) { gvwBigMemory.ItemsSource = Enumerable.Range(1, 100); } private void BtnNew_Click(object sender, RoutedEventArgs e) { gvwMinMemory.ItemsSource = Enumerable.Range(1, 100); } }
很简单,就是让 GridView 加载 100 个。
好,走起!
![](http://images0.cnblogs.com/blog/484187/201506/110818088946243.png)
初始运行占用 40.6 MB 内存,当然这个值可能下次运行就不一样了,多少会有点波动。
接下来我们加载旧版:
![](http://images0.cnblogs.com/blog/484187/201506/110818095821101.png)
令人吃惊,一瞬间就跑到 250.6 MB 内存了。
那我们再来看看新的版本,记得先将上面这个关掉,重新打开,否则影响结果。
新版:
![](http://images0.cnblogs.com/blog/484187/201506/110818103486999.png)
44.6 MB!基本没发生任何的变化。可见威力很强大,说明我们的代码起作用了。
结语:
可以见到这点小小的优化能带来多大的影响。另外由于 GridView 默认使用了虚拟化,所以实际上并没有加载到 100个,但是仍然可以见到旧版的内存占用十分厉害, 所以根本没法想象真真正正加载 100 个的时候有多壮观。小小的
细节可能会引起巨大的变化,考虑到还有众多 512 MB 内存的 Windows Phone 用户,这点小小的细节仍然很有必
要去做的。
相关文章推荐
- Android 之 布局属性
- Apc缓存Opcode(转)
- HDU Count 101 解题报告
- 爱树莓的小派
- MapReduce之RecordReader组件源码解析及实例
- 在Rhel 6.2或centos6 中建立163 yum 源
- Codeforces Round #307 (Div. 2)
- Maven配置-使用Maven创建WEB项目支持Tomcat目录部署
- Python实战之神经网络(1)
- 冒泡排序—while语句实现
- 深入Windows内核——C++中的消息机制
- LevelDB原理探究和代码分析(下)
- 6.面向对象程序设计
- 敏捷开发下, 如何将需求分析,架构(软件)设计,开发与测试,一气呵成式的结合且高效的完成 ?
- [算法]分治算法(Divide and Conquer)
- poj3414(用bfs模拟并回溯)
- hdoj 1796 How many integers can you find 【容斥原理】
- 西南石油大学 LaTeX Beamer模板
- 运用layerlist在5.0以下的android上实现material design的阴影效果
- Castle连接多数据库配置