一、应用场景

在淘宝应用首页,会有很多张图片,而这些首页图片不会经常改变,所以就需要缓存下来。这样就不必每次都从网络获取。

二、比较对象

1.系统缓存

对于系统缓存,我们不需要做什么处理。只需要把网络图片的URL赋值给Image控件就行了。这样系统就会在每次需要用到图片的时候,有限查找缓存里有没有之前下载好的。

2.自建缓存区域

自建缓存不给Image控件赋URL,而是把图片DownLoad下来,生成一个bitmap,然后把bitmap赋值给Image。同时将这个bitmap存储下来。当下次要用到这幅图的时候,就直接从存储的位置找到这幅图。

三、自建缓存方法

下边这段代码将uri[]数组中的图片下载下来,然后通过WriteToFile()函数将图片保存到本地,同时,记下存储的文件名。

SoftwareBitmap sb = await DownloadImage(uri[i]);
if (sb != null)
{
  //sb = await ReadFromFile(fileName[i]);
  SoftwareBitmapSource source = new SoftwareBitmapSource();
  await source.SetBitmapAsync(sb);
  this.insideImage.Source = source;
  sb = await DownloadImage(uri[i]);
  fileName[i] = await WriteToFile(sb);
}

当你需要使用图片的时候,使用下列代码,通过ReadFromFile()函数将图片读取出来就行了。

for (int i = ; i < ; i++)
{
  //SoftwareBitmap sb = await DownloadImage(uri[i]);
  SoftwareBitmap sb = await ReadFromFile(fileName[i]);
  SoftwareBitmapSource source = new SoftwareBitmapSource();
  await source.SetBitmapAsync(sb);
  this.insideImage.Source = source;
  //source.Dispose();
}

四、效率对比

下边我通过对比两种缓存机制发现各有用武之地。

1.对于几百K到几兆的大图片,系统缓存有速度优势。

2.对于几K到几十K的小图片,自建缓存区有速度优势。

测试背景1:三张大图片,循环33次(共99次)

图片大小:338k 618k 1810k

PC测试

         

系统缓存(CPU周期)

3066584

3058505

3079367

3078989

3076976

自建缓存(CPU周期)

53669280

51842991

52839051

52078772

52305373

Phone测试

       

系统缓存(CPU周期)

31852799

32008575

32200748

31970601

31839003

自建缓存(CPU周期)

741909215

750950455

765863510

760865505

781048686

结论一:对于几百K到几兆的大图片,系统缓存有速度优势。

测试背景2:三张小图片,循环33次(共99次)

图片大小:3k 6k 60k

PC测试

系统缓存(CPU周期)

3057284

3057637

3080880

3063350

3059105

自建缓存(CPU周期)

1316247

1318369

1364584

1333684

1362956

Phone测试

系统缓存(CPU周期)

32085084

31751734

31744715

31852230

32064768

自建缓存(CPU周期)

27114317

26041012

26821794

27365796

30211258

结论二:对于几K到几十K的小图片,自建缓存区有速度优势。

手机淘宝项目测试数据:

测试背景:50张小图片,循环一次(共50次)

系统缓存

CPU周期

23689650

21589548

25409150

25186302

23121251

 

RAM

51

52

50

52

52

             
             

自建缓存

CPU周期

3186761

2892837

2963193

2942235

2741501

 

RAM

61

63

61

60

59

PS:RAM占用是峰值,稳定后两种方式RAM占用相同。

五、测试方法

通过给一个Image控件赋值,来看到效果。

1、系统缓存

系统缓存测试不能通过直接改变url的方式,因为系统缓存是异步的,他不会等一个图片加载好再加载另一个图,而是直接忽略了之前的改变。

private async void test1()
{
  stopwatch.Reset();
  stopwatch.Start();
  BitmapImage bi = new BitmapImage();
  bi.UriSource = new Uri(uri[]);
  this.insideImage.Source = bi;
} private void insideImage_ImageOpened(object sender, RoutedEventArgs e)
{
  times++;
  if (times == )
  {
    stopwatch.Stop();
    textBox.Text = "任务"+testnum.ToString()+"用时:" + stopwatch.ElapsedTicks + ".";
    return;
  }   BitmapImage bi = new BitmapImage();
  bi.UriSource = new Uri(uri[times]);
  this.insideImage.Source = bi;
}

2、自建缓存

private async void test2()
{
  stopwatch.Reset();
  stopwatch.Start();
  for (int i = ; i < ; i++)
  {
    //SoftwareBitmap sb = await DownloadImage(uri[i]);
    SoftwareBitmap sb = await ReadFromFile(fileName[i]);
    SoftwareBitmapSource source = new SoftwareBitmapSource();
    await source.SetBitmapAsync(sb);
    if (i % == )
    {
      this.insideImage.Source = source;
    }
    else if (i % == )
    {
      this.insideImage1.Source = source;
    }
    else if (i % == )
    {
      this.insideImage2.Source = source;
    }
    //source.Dispose();
  }
  stopwatch.Stop();
  textBox.Text = "任务" + testnum.ToString() + "用时:" + stopwatch.ElapsedTicks + ".";
}

附:关键代码代码

ReadFromFile()函数通过文件名读取图片 ,特别注意这句话

SoftwareBitmapsoftwareBitmap = awaitdecoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);

一定要加上编码方式,不然会报错。

public async Task<SoftwareBitmap> ReadFromFile(string filename)
{
  StorageFile file = await _localFolder.CreateFileAsync(filename, CreationCollisionOption.OpenIfExists);
  //var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri( filename));
  using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read))
  {
    // Create the decoder from the stream
    BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
    // Get the SoftwareBitmap representation of the file
    SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
    return softwareBitmap;
  }
}

WriteToFile()函数将bitmap写入存储区

public async Task<string> WriteToFile(SoftwareBitmap softwareBitmap)
{
  string fileName = Path.GetRandomFileName();   if (softwareBitmap != null)
  {
    // save image file to cache
    StorageFile file = await _localFolder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);
    using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
    {
      BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
      encoder.SetSoftwareBitmap(softwareBitmap);
      await encoder.FlushAsync();
  }
}   return fileName;
}

DownloadImage()函数通过url下载图片,返回bitmap

private async Task<SoftwareBitmap> DownloadImage(string url)
{
  try
  {
    HttpClient hc = new HttpClient();
    HttpResponseMessage resp = await hc.GetAsync(new Uri(url));
    resp.EnsureSuccessStatusCode();
    IInputStream inputStream = await resp.Content.ReadAsInputStreamAsync();
    IRandomAccessStream memStream = new InMemoryRandomAccessStream();
    await RandomAccessStream.CopyAsync(inputStream, memStream);
    BitmapDecoder decoder = await BitmapDecoder.CreateAsync(memStream);
    SoftwareBitmap softBmp = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
    return softBmp;
  }
  catch (Exception ex)
  {
    return null;
  }
}

淘宝UWP--自定义图片缓存的更多相关文章

  1. 我的面板我做主 -- 淘宝UWP中自定义Panel的实现

    在Windows10 UWP开发平台上内置的XMAL布局面板包括RelativePanel.StackPanel.Grid.VariableSizedWrapGrid 和 Canvas.在开发淘宝UW ...

  2. 飞流直下的精彩 -- 淘宝UWP中瀑布流列表的实现

    在淘宝UWP中,搜索结果列表是用户了解宝贝的重要一环,其中的图片效果对吸引用户点击搜索结果,查看宝贝详情有比较大的影响.为此手机淘宝特意在搜索结果列表上采用了2种表现方式:一种就是普通的列表模式,而另 ...

  3. 淘宝UWP中的100个为什么

    从淘宝UWP第一版发布到现在,已经有十个月了,期间收到了用户各种各样的反馈,感谢这些用户的反馈,指导我们不断的修正.完善应用.但是也有一部分需求或建议,由于资源或技术的限制,目前确实无法做到,只能对广 ...

  4. 剁手党也有春天 -- 淘宝 UWP ”比较“功能诞生记

    前言 网购已经不再是现在的时髦,而变成了我们每天的日常生活.上网已经和买买买紧密地联系在了一起,成为了我们的人生信条.而逛街一词,越来越多地变成了一种情怀.有时候我们去逛街,要么是为了打发时间,要么是 ...

  5. PC版淘宝UWP揭秘

    经过第一轮内测后的bug数量:65 2015/11/27 - bug数量 = 60 2015/11/30 - bug数量 = 53 2015/12/1 - bug数量 = 49 2015/12/2 - ...

  6. 从淘宝 UWP 的新功能 -- 比较页面来谈谈 UWP 的窗口多开功能

    前言 之前在 剁手党也有春天 -- 淘宝 UWP ”比较“功能诞生记 这篇随笔中介绍了一下 UWP 淘宝的“比较”新功能呱呱坠地的过程.在鲜活的文字背后,其实都是程序员不眠不休的血泪史(有血有泪有史) ...

  7. 淘宝UWP桌面版已经发布

    目前正在等待应用商店的检测,很快会可以下载. 谢谢各位园主针对淘宝UWP 桌面版(又叫PC版,HD版等等)给予的feedback,在这里统一回复一下,就不一一感谢了. 有一件事需要说明一下,请看下图: ...

  8. 手机淘宝UWP

    各位园主好! bug 走势: 哪天bug 足够少,哪天就可以发布了  :) 2015/10/23: 49 2015/10/26: 40 2015/10/27: 36 2015/10/28: 30 20 ...

  9. UWP关于图片缓存的那些破事儿

    看似简单的功能,实施起来却是有着一堆大坑. 按着基本功能来写吧 1.选择图片并显示到Image控件中 2.图片序列化为byte数组以及反序列化 3.本地存储与读取 1.选择图片: 逻辑就是使用File ...

随机推荐

  1. Flask备注二(Configurations, Signals)

    Flask备注二(Configuration, Signals) Flask是一个使用python开发Web程序的框架.依赖于Werkzeug提供完整的WSGI支持,以及Jinja2提供templat ...

  2. 110.Balanced Binary Tree Leetcode解题笔记

    110.Balanced Binary Tree Given a binary tree, determine if it is height-balanced. For this problem, ...

  3. 一点一滴学shell-Shell expr的用法 (转)

    原文链接:http://desheng666.blog.163.com/blog/static/4908408220121643953425/ expr命令一般用于整数值,但也可用于字符串.一般格式为 ...

  4. [08]APUE:进程控制

    [a] getpid / getppid / getuid / geteuid / getgid / getegid #include <unistd.h> pid_t getpid(vo ...

  5. Python赋值语句与深拷贝、浅拷贝的区别

    参考:http://stackoverflow.com/questions/17246693/what-exactly-is-the-difference-between-shallow-copy-d ...

  6. Maven仓库管理-Nexus

    Maven仓库管理-Nexus @import url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=style& ...

  7. Javascript重要知识点梳理

    Javascript重要知识点梳理 一.Javascript流程控制 js中常用的数据类型 var关键字的使用 if – else if – else switch while for 二.Javas ...

  8. [C#基础实例]指定地址解析图片并下载

    需求:查找页面图片并下载至本地: 实现: 首先:读取通过网络html内容,并用正则表达式查找图片地下. 其次:使用WebRequest.Create创建图片请求. 最后:把获取图片网络流数据通过Fil ...

  9. memcached总结

    Memcached说明文档 Memcached是什么? Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数 ...

  10. new出对象的作用

    new调用了构造函数以后 构造函数会返回一个对象的实例