Windows phone Image cache Converter

原文地址

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 Image
                return bm;
            }
            else
            {
                var bm = new BitmapImage(imageFileUri);
                return bm;
            }
        }

        private static object DownloadFromWeb(Uri imageFileUri)
        {
            var m_webClient = new WebClient(); //Load from internet
            var 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 storage
            using (
                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";
        }
    }




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值