惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
Vercel News
Vercel News
F
Fortinet All Blogs
月光博客
月光博客
G
Google Developers Blog
博客园 - Franky
GbyAI
GbyAI
The Cloudflare Blog
I
InfoQ
雷峰网
雷峰网
WordPress大学
WordPress大学
罗磊的独立博客
大猫的无限游戏
大猫的无限游戏
T
The Blog of Author Tim Ferriss
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 聂微东
小众软件
小众软件
腾讯CDC
B
Blog
量子位
V
V2EX
S
SegmentFault 最新的问题
Google DeepMind News
Google DeepMind News

博客园 - kiminozo

UAP如何根据DeviceFamily显示不同的页面 Windows 10 响应式设计和设备友好的开发 Windows Phone Toolkit for WP8 已经出了 代码分享 ScrollViewerListener 获取ScrollViewer的位置改变 经验 C#手动同步的滥用实例 WP7技巧 扩展【共享...】按钮 Bangumi 番組計劃 WP手机客户端发布 WP7进阶技巧 自定义Toast 提示动画效果 WP7自定义控件 TabSwitch控件 模拟Windows phone 开始菜单的瓦片动画 WP7自定义控件 评分控件 WP7应用开发笔记 TiltEffect为控件添加倾斜的触控响应效果 从FLC中学习的设计模式系列-结构型模式(3)-享元模式 用代理类包装异步调用方法实现异步命令 解决log4net在.net 4.0 ClientProfile下无法使用 从FLC中学习的设计模式系列-结构型模式(2)-装饰 从FLC中学习的设计模式系列-结构型模式(1)-适配器 从FLC中学习的设计模式系列-创建型模式(5)-原型 从FLC中学习的设计模式系列-创建型模式(4)-建造者
WP7应用开发笔记 继承BitmapSource并使用独立存储来缓存远程...
kiminozo · 2012-02-28 · via 博客园 - kiminozo

作为Web App访问远程图片是经常的遇到功能,Wp本身提供了Image 很好的支持通过图片的Uri显示图片

public ImageSource Source { get; set; }


<Image Source="https://www.google.com/intl/en_com/images/srpr/logo3w.png" />

为了减少网络流量,需要将图片缓存到本地数据存储中。复习一下WP的本地数据存储:

Windows Phone 本地数据存储

Windows Phone 应用程序可以使用独立存储将数据储存到手机本地。应用程序可以通过三种方式储存数据:

  1. 设置:使用 IsolatedStorageSettings 类将数据存储为键/值对。
  2. 文件和文件夹:使用 IsolatedStorageFile 类存储文件和文件夹。
  3. 本地数据库:7.1新增,只能支持LINQ TO SQL ,不能写SQL语句。

本地存储图片

首先图片应该选择IsolatedStorageFile来存储:

WP提供了一个叫IsolatedStorageFileStream的Stream和FileStream操作一样

using (var fileStream = isolatedStorageFile.OpenFile(filePath, FileMode.OpenOrCreate, FileAccess.Write)) 
{
stream.CopyTo(fileStream);
}

缓存的思路

image

现在是思路是首先检查是否被缓存里,首先定义一个公用的缓存文件夹,在静态构造函数中创建文件夹

private const string CacheDirectory = "CachedImages"; 

static StorageCachedImage()
{

//创建缓存目录
using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
{
if (!isolatedStorageFile.DirectoryExists(CacheDirectory))
{
isolatedStorageFile.CreateDirectory(CacheDirectory);
}
}
}

然后将Url转换成文件名,我的方法比较简单直接替换’/’符号。使用FileExists判断文件是否存在

//文件路径 
filePath = Path.Combine(CacheDirectory, uriSource.AbsolutePath.TrimStart('/').Replace('/', '_'));

/// <summary>
/// 打开缓存源
/// </summary>
private void OpenCatchSource()
{
bool exist;
using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
{
exist = isolatedStorageFile.FileExists(filePath);
}
if (exist)
{
SetCacheStreamSource();
}
else
{
SetWebStreamSource();
}
}

如果没有缓存则通过Uri下载图片并保存到IsolatedStorageFile。

使用httpWebRequest实现下载,使用IsolatedStorageFileStream保存图片

/// <summary> 
/// 下载Uri中的图片
/// </summary>
private void SetWebStreamSource()
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(uriSource);
httpWebRequest.AllowReadStreamBuffering = true;
httpWebRequest.BeginGetResponse(ResponseCallBack, httpWebRequest);
}

/// <summary>
/// 下载回调
/// </summary>
/// <param name="asyncResult"></param>
private void ResponseCallBack(IAsyncResult asyncResult)
{
var httpWebRequest = asyncResult.AsyncState as HttpWebRequest;
if(httpWebRequest == null)return;
try
{
var response = httpWebRequest.EndGetResponse(asyncResult);
using(var stream = response.GetResponseStream())
using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
using (var fileStream = isolatedStorageFile.OpenFile
(filePath, FileMode.OpenOrCreate, FileAccess.Write))
{
stream.CopyTo(fileStream);//保存到本地
}
Dispatcher.BeginInvoke(SetCacheStreamSource);
}
catch(Exception err)
{
Debug.WriteLine(err.Message);
}
}

保存到本地后下载,用IsolatedStorageFileStream打开本地图像流,并通过父类的SetSource设置图片流。

private void SetCacheStreamSource() 
{
using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
using (var stream = isolatedStorageFile.OpenFile(filePath, FileMode.Open, FileAccess.Read))
{
SetSource(stream);
}

完整代码如下:

View Code

using System;
using System.Diagnostics;
using System.IO;
using System.IO.IsolatedStorage;
using System.Net;
using System.Windows.Media.Imaging;

namespace KimiStudio.Controls
{
/// <summary>
/// 独立存储缓存的图片源
/// </summary>
public sealed class StorageCachedImage : BitmapSource
{
private readonly Uri uriSource;
private readonly string filePath;
private const string CacheDirectory = "CachedImages";

static StorageCachedImage()
{

//创建缓存目录
using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
{
if (!isolatedStorageFile.DirectoryExists(CacheDirectory))
{
isolatedStorageFile.CreateDirectory(CacheDirectory);
}
}
}

/// <summary>
/// 创建一个独立存储缓存的图片源
/// </summary>
/// <param name="uriSource"></param>
public StorageCachedImage(Uri uriSource)
{
this.uriSource = uriSource;

//文件路径
filePath = Path.Combine(CacheDirectory, uriSource.AbsolutePath.TrimStart('/').Replace('/', '_'));
OpenCatchSource();
}

/// <summary>
/// 打开缓存源
/// </summary>
private void OpenCatchSource()
{
bool exist;
using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
{
exist = isolatedStorageFile.FileExists(filePath);
}
if (exist)
{
SetCacheStreamSource();
}
else
{
SetWebStreamSource();
}
}

/// <summary>
/// 设置缓存流到图片
/// </summary>
private void SetCacheStreamSource()
{
using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
using (var stream = isolatedStorageFile.OpenFile(filePath, FileMode.Open, FileAccess.Read))
{
SetSource(stream);
}
}

/// <summary>
/// 下载Uri中的图片
/// </summary>
private void SetWebStreamSource()
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(uriSource);
httpWebRequest.AllowReadStreamBuffering = true;
httpWebRequest.BeginGetResponse(ResponseCallBack, httpWebRequest);
}

/// <summary>
/// 下载回调
/// </summary>
/// <param name="asyncResult"></param>
private void ResponseCallBack(IAsyncResult asyncResult)
{
var httpWebRequest = asyncResult.AsyncState as HttpWebRequest;
if(httpWebRequest == null)return;
try
{
var response = httpWebRequest.EndGetResponse(asyncResult);
using(var stream = response.GetResponseStream())
using (var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
using (var fileStream = isolatedStorageFile.OpenFile
(filePath, FileMode.OpenOrCreate, FileAccess.Write))
{
stream.CopyTo(fileStream);
}
Dispatcher.BeginInvoke(SetCacheStreamSource);
}
catch(Exception err)
{
Debug.WriteLine(err.Message);
}
}
}

}

测试

定义一个Image

Uri uriSource = new Uri(@”https://www.google.com/intl/en_com/images/srpr/logo3w.png”);

image1.ImageSource = new StorageCachedImage(uriSource);

用IsoStoreSpy查看(这里是我APP实际的图)

%Z7VL7E~500N8AI$NFO2Q]T