当前位置: 代码迷 >> 综合 >> Windows phone Image cache Converter
  详细解决方案

Windows phone Image cache Converter

热度:78   发布时间:2023-12-16 13:37:44.0

原文地址

http://chandermani.blogspot.com/2012/05/caching-images-downloaded-from-web-on.html


目的

      应用中用到图片的地方,每次都要网络上拉取,非常耗费流量,效率也不高。

应该将将程序中所有图片缓存到IsolatedStorage。写成一个Converter,可以

应用在所有Image Binding的地方。


策略

   1.判断Uri地址是否http或者https的scheme

   2.是Http或者Https

   2.1本地有缓存优先读取本地的缓存

   2.2无网络的情况下:读取默认图像

   2.3有网络而且无缓存的时候才到网上获取图像

   3.非网络资源直接读取即可


使用方法

   1.phone:PhoneApplicationPage.Resources里面定义Converter

<phone:PhoneApplicationPage.Resources><converter:CacheImageFileConverter x:Key="CacheConverter"/>
</phone:PhoneApplicationPage.Resources>

   2.引用Converter

xmlns:converter="clr-namespace:ProjectName.Converter"


   3.Image控件中绑定

<Image x:Name="ImgBackground"Source="{Binding yourProperty,Converter={StaticResource CacheConverter},ConverterParameter=''}" />



Bug

   原文的代码里面

   这行代码:

  private static IsolatedStorageFile _storage = IsolatedStorageFile.GetUserStoreForApplication();
   会引发TypeInitializationException ,导致在Blend里面,使用本Converter的datatemplete无法预览。

   原因是:类的静态成员在初始化时如果出现异常,类的其它静态成员或对该类进行初始化都会抛出这个异常。

     解决方法:如果类中存在静态成员,应确保其初始化时不会抛出异常,否则会影响对该类的正常


   修改如下可以解决:

private static IsolatedStorageFile _storage;public CacheImageFileConverter(){try{if (_storage == null){_storage = IsolatedStorageFile.GetUserStoreForApplication();}}catch (IsolatedStorageException e){Debug.WriteLine(e);}}




完整代码

   /// <summary>///     Caches the image that gets downloaded as part of Image control Source property./// </summary>public class CacheImageFileConverter : IValueConverter{private const string ImageStorageFolder = "TempImages";private static IsolatedStorageFile _storage;public CacheImageFileConverter(){try{if (_storage == null){_storage = IsolatedStorageFile.GetUserStoreForApplication();}}catch (IsolatedStorageException e){Debug.WriteLine(e);}}public object Convert(object value, Type targetType, object parameter, CultureInfo culture){var path = value as Uri;if (String.IsNullOrEmpty(path.ToString())) return null;var imageFileUri = path;if (imageFileUri.Scheme == "http" || imageFileUri.Scheme == "https"){// 先看缓存if (_storage.FileExists(GetFileNameInIsolatedStorage(imageFileUri))){return ExtractFromLocalStorage(imageFileUri);}// 再看网络情况if (!DeviceNetworkInformation.IsNetworkAvailable){return LoadDefaultIfPassed(imageFileUri, (parameter ?? string.Empty).ToString());}// 最后再网上获取return DownloadFromWeb(imageFileUri);}// 不是网络图片,应用内的素材var bm = new BitmapImage(imageFileUri);return bm;}public object ConvertBack(object value, Type targetType, object parameter,CultureInfo culture){throw new NotImplementedException();}private static object LoadDefaultIfPassed(Uri imageFileUri, string defaultImagePath){string defaultImageUri = (defaultImagePath ?? string.Empty);if (!string.IsNullOrEmpty(defaultImageUri)){var bm = new BitmapImage(new Uri(defaultImageUri, UriKind.Relative)); //Load default Imagereturn bm;}else{var bm = new BitmapImage(imageFileUri);return bm;}}private static object DownloadFromWeb(Uri imageFileUri){var m_webClient = new WebClient(); //Load from internetvar bm = new BitmapImage();m_webClient.OpenReadCompleted += (o, e) =>{if (e.Error != null || e.Cancelled) return;WriteToIsolatedStorage(IsolatedStorageFile.GetUserStoreForApplication(), e.Result,GetFileNameInIsolatedStorage(imageFileUri));bm.SetSource(e.Result);e.Result.Close();};m_webClient.OpenReadAsync(imageFileUri);return bm;}private static object ExtractFromLocalStorage(Uri imageFileUri){string isolatedStoragePath = GetFileNameInIsolatedStorage(imageFileUri); //Load from local storageusing (IsolatedStorageFileStream sourceFile = _storage.OpenFile(isolatedStoragePath, FileMode.Open,FileAccess.Read)){var bm = new BitmapImage();bm.SetSource(sourceFile);return bm;}}private static void WriteToIsolatedStorage(IsolatedStorageFile storage, Stream inputStream,string fileName){IsolatedStorageFileStream outputStream = null;try{if (!storage.DirectoryExists(ImageStorageFolder)){storage.CreateDirectory(ImageStorageFolder);}if (storage.FileExists(fileName)){storage.DeleteFile(fileName);}outputStream = storage.CreateFile(fileName);var buffer = new byte[32768];int read;while ((read = inputStream.Read(buffer, 0, buffer.Length)) > 0){outputStream.Write(buffer, 0, read);}outputStream.Close();}catch{//We cannot do anything here.if (outputStream != null) outputStream.Close();}}/// <summary>///     Gets the file name in isolated storage for the Uri specified. This name should be used to search in the isolated storage./// </summary>/// <param name="uri">The URI.</param>/// <returns></returns>public static string GetFileNameInIsolatedStorage(Uri uri){return ImageStorageFolder + "\\" + uri.AbsoluteUri.GetHashCode() + ".img";}}




  相关解决方案