通常情况下,我们的程序需要从服务器读取图片,但如果需要不止一次读取某一张图片的话,就需要做本地缓存了,这样既为用户省一点流量,又能显得你的APP很快。

  假如你已经知道了某一张图片的地址,那么第一件事就是要把这张图片下载下来;当然如果是一次性读取的话,可以直接把图片地址给Image控件或者给Bitmapimage对象(实际上这二者是没有去别的),但这无法存到本地,只作为显示用;但是我们要做的是保存到本地,这样肯定是不行的。现在我们就要用到HTTP的东西了,请看下面的代码:

 async static public Task<IInputStream> GetStreamAsync(string url)
{ httpClient = new HttpClient();
var response = await httpClient.GetInputStreamAsync(new Uri(url));
return response;
} async static public Task<IBuffer> GetBufferAsync(string url)
{ httpClient = new HttpClient(); var ResultStr = await httpClient.GetBufferAsync(new Uri(url));
return ResultStr;
}

这两个静态方法分别获取url地址的buffer数据和输入流。有了buffer或者stream之后就可以进行下一步-保存。

  当我们下载完成后,首先要做的很有可能是先显示出来,然后再保存,所以先把数据写入到图片对象中:

这里有两种方法:

1.WriteableBitmap

 protected async Task<WriteableBitmap> GetWriteableBitmapAsync(string url)
{
try
{
IBuffer buffer = await GetBufferAsync(url);
if (buffer != null)
{
BitmapImage bi = new BitmapImage();
WriteableBitmap wb = null; Stream stream2Write;
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{ stream2Write = stream.AsStreamForWrite(); await stream2Write.WriteAsync(buffer.ToArray(), , (int)buffer.Length); await stream2Write.FlushAsync();
stream.Seek(); await bi.SetSourceAsync(stream); wb = new WriteableBitmap(bi.PixelWidth, bi.PixelHeight);
stream.Seek();
await wb.SetSourceAsync(stream); return wb;
}
}
else
{
return null;
}
}
catch
{
return null;
}
}

2.SoftwareBitmap

public async Task<SoftwareBitmap> GetSoftwareBitmapAsync(string url)
{
try
{
IInputStream inputStream = await GetSteramAsync(url);
IRandomAccessStream memStream = new InMemoryRandomAccessStream();
await RandomAccessStream.CopyAsync(inputStream, memStream);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(memStream);
SoftwareBitmap sb = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
return sb;
}
catch
{
return null;
}
}

这两种都可以作为展示图像的数据源,其中WriteableBitmap可以直接给Image.Source , SoftwareBitmap这需要转为SoftwareBitmap:

          SoftwareBitmapSource sbs = new SoftwareBitmapSource();
sbs.SetBitmapAsync(sb);

接下来就是保存了:WriteableBitmap:

 public async Task SaveImageAsync(WriteableBitmap image, string filename)
{
try
{
if (image == null)
{
return;
}
Guid BitmapEncoderGuid = BitmapEncoder.JpegEncoderId;
if (filename.EndsWith("jpg"))
BitmapEncoderGuid = BitmapEncoder.JpegEncoderId;
else if (filename.EndsWith("png"))
BitmapEncoderGuid = BitmapEncoder.PngEncoderId;
else if (filename.EndsWith("bmp"))
BitmapEncoderGuid = BitmapEncoder.BmpEncoderId;
else if (filename.EndsWith("tiff"))
BitmapEncoderGuid = BitmapEncoder.TiffEncoderId;
else if (filename.EndsWith("gif"))
BitmapEncoderGuid = BitmapEncoder.GifEncoderId;
var folder = await _local_folder.CreateFolderAsync("images_cache", CreationCollisionOption.OpenIfExists);
var file = await folder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting); using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoderGuid, stream);
Stream pixelStream = image.PixelBuffer.AsStream();
byte[] pixels = new byte[pixelStream.Length];
await pixelStream.ReadAsync(pixels, , pixels.Length);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,
(uint)image.PixelWidth,
(uint)image.PixelHeight,
96.0,
96.0,
pixels);
await encoder.FlushAsync();
}
}
catch
{ }
}
public async Task WriteToFileAsync(StorageFolder folder,SoftwareBitmap sb,string fileName)
{ if (sb != null)
{
// save image file to cache
StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
encoder.SetSoftwareBitmap(sb);
await encoder.FlushAsync();
}
}
}

怎么样,是不是很简单?

UWP开发中两种网络图片缓存方法的更多相关文章

  1. 说一说Web开发中两种常用的分层架构及其对应的代码模型

    昨天妹子让我帮她解决个问题,本以为可以轻松搞定,但是打开他们项目的一瞬间,我头皮发麻.本身功能不多的一个小项目,解决方案里竟然有几十个类库.仅仅搞明白各个类库的作用,代码层次之间的引用关系就花了一个多 ...

  2. Python中两种处理错误方法的比较

    我所说的处理错误的方法,其实是try:,except和raise这两种. 首先抛出一个实例, dictt={'a':1,'b':2,'c':3} try: if dictt['d']>1: #字 ...

  3. Cesium 中两种添加 model 方法的区别

    概述 Cesium 中包含两种添加 model 的方法,分别为: 通过 viewer.entities.add() 函数添加 通过 viewer.scene.primitives.add() 函数添加 ...

  4. Mat中两种像素遍历方法比较

    小白,入门中,不足其指正.刚刚接触opencv,从一个Matlab风格的编程环境突然跳转到C++,实在有些不适.单就pixels scanning花了好长时间研究.opencv-tutorials给出 ...

  5. python中两种拷贝目录方法的比较

    首先是用python自己的api: shutil.copytree('./build/tested/doc', './build/tested/build/doc') 优点是改变平台时不需要修改代码, ...

  6. JAVA 中两种判断输入的是否是数字的方法__正则化_

    JAVA 中两种判断输入的是否是数字的方法 package t0806; import java.io.*; import java.util.regex.*; public class zhengz ...

  7. jsp中两种include的区别【转】

    引用文章:http://www.ibm.com/developerworks/cn/java/j-jsp04293/ http://www.cnblogs.com/lazycoding/archive ...

  8. IOS开发-几种截屏方法

    IOS开发-几种截屏方法 1.        UIGraphicsBeginImageContextWithOptions(pageView.page.bounds.size, YES, zoomSc ...

  9. GET和POST两种基本请求方法(转自博主--在途中#)

    GET和POST两种基本请求方法的区别 GET和POST是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一二. 最直观的区别就是GET把参数包含在URL中,POST通过req ...

随机推荐

  1. 实现iOS图片等资源文件的热更新化(四): 一个最小化的补丁更新逻辑

    简介 以前写过一个补丁更新的文章,此处会做一个更精简的最小化实现,以便于集成.为了使逻辑具有通用性,将剥离对AFNetworking和ReativeCocoa的依赖.原来的文章,可以先看这里: htt ...

  2. .NET的EF框架中:在应用程序配置文件中找不到名为“”的连接字符串问题

    今天在使用EF Code First框架时,当把模型都定义好了,想通过程序包管理控制台利用enable-migrations –force来生成数据库表的时候报错了,如下: 找不到连接字符串,但是我仔 ...

  3. Socket开发框架之框架设计及分析

    虽然在APP应用.Web应用.Winform应用等大趋势下,越来越多的企业趋向于这些应用系统开发,但是Socket的应用在某些场合是很必要的,如一些停车场终端设备的接入,农业或者水利.压力监测方面的设 ...

  4. 紫橙绿蓝的jQuery幻灯片切换

      效果展示 http://hovertree.com/texiao/jquery/77/ 看惯了左右切换的幻灯片,何问起向您推荐一个新颖的,旋转切换,通过点击按钮的相应区域可以使幻灯片以旋转的方式来 ...

  5. 【C#】第3章补充(一)如何在WPF中绘制正弦曲线

    分类:C#.VS2015 创建日期:2016-06-19 使用教材:(十二五国家级规划教材)<C#程序设计及应用教程>(第3版) 一.要点 本例子提前使用了教材第13章介绍的基本知识. 二 ...

  6. 算法:冒泡排序(python版)

    1.将n个元素从大到小排序后,选择第k个大的元素 #!/usr/bin/env python #coding -*- utf:8 -*- #冒泡排序选第k个元素 import random impor ...

  7. 网上图书商城3--Book模块

    小技巧一:分页 ①PageBean<Book> findByCriteria(List<Expression> exprList, int pc)  --- 通用的查询方法(p ...

  8. 七个结构模式之装饰者模式(Decorator Pattern)

    定义: 使用组合的方法,动态给一个类增加一些额外的功能,避免因为使用子类继承而导致类继承结构复杂.并且可以保持和被装饰者同一个抽象接口,从而使客户端透明. 结构图: Component:抽象构件类,定 ...

  9. sql server和mysql中分别实现分页功能

    MySQL 在MySQL中,可以用 Limit 来查询第 m 列到第 n 列的记录, 例如: select * from tablename limit m, n sql="select * ...

  10. Frameless - 用于预览 iOS8 原型的浏览器

    Frameless 是一个用于在 iOS8 中预览产品原型的浏览器.可以可以帮助那些需要一个简单的方法来预览 iOS 设备上的原型设计和开发效果.没有状态栏,通过手势控制浏览器的历史以及键盘的显示. ...