Windows 8 Store Apps xml资源自定义缓存

提示:下面的这种思路从一开始就很不妥,废弃 (2019.6.3),严厉批评!浏览器

对于Win8中rss新闻阅读类应用必定会面临这种问题,那就是若是断开了网络链接rss的文章该怎么呈现?缓存

我认为既然在联网状态下我已经看到过的信息在断网以后依然可以看到。此时,该如何缓存的问题就出来了。网络

若是类比浏览器缓存,咱们天然会问对于Win8 app获取网络数据操做系统会自动帮咱们缓存一份吗?答案是确定的。让咱们看看它在哪里。app

> app操做系统自身缓存异步

打开应用的ApplicationData文件夹,在AC文件夹下将系统所保护的隐藏文件显示出来async

能够看到隐藏的INetCache、INetCookies和INetHistory,很明显是用来缓存的。经过查看每个文件夹能够发现,咱们的xml数据缓存到了INetCache文件夹下。学习

点击里面的每个文件夹就能够看到xml中所包含的图片,以及xml文件。编码

以上是操做系统的缓存,在断网的状况下数据仍是能保留的确省了App不小的心。但有一点,若是时间长了缓存的内容愈来愈多占用的空间磁盘比较大,或者说一次缓存就占用的空间比较多,对有些人来讲这没什么。但对我我的,我以为若是由于个人软件占用磁盘空间过多给用户带来困扰,我内心会很很差过。因此,我必定要给用户可以清理缓存的功能。url

直接清理操做系统缓存的文件能够吗?答案是不能够,由于无权访问那个文件夹。spa

接下来的问题又来了,既然咱们不能清理系统缓存的,那咱们就不用系统缓存,咱们本身去实现自主缓存。说作就作(前提是已经想好了)。

 

> xml资源自主缓存的实现

下面是思路和关键代码:

一、从网络获取XMLDocument格式的数据

可使用XmlDoucment的LoadFromUriAsync方法来获取xml格式的数据

1 await XmlDocument.LoadFromUriAsync(new Uri("http://xxx")),"CachedFeed")

若是须要注意编码格式的话可使用StreamReader类来读取

1 XmlDocument xml = new XmlDocument();
2 
3 StreamReader reader = new StreamReader(await client.GetStreamAsync(url), Encoding.GetEncoding("utf-8"));
4 
5 string rss = await reader.ReadToEndAsync();
6 
7 xml.LoadXml(rss);   


固然你也可使用其余方法来获取指定xml的uri的byte,而后再进行转换来获取xml格式数据

1 byte[] urlContents = await client.GetByteArrayAsync(url);

(微软有示例叫作Async Sample Bridging between .NET and Windows Runtime WhenAny和Async Sample Reentrancy in Windows Store Apps (C# and Visual Basic),这两个彻底能够知足异步的要求,视状况而定)

二、从XMLDocument格式的数据以后从中选出是图片的标签

1 Content.GetElementsByTagName(MediaElementTag)

三、 遍历其中每个item的图片标签进行修改和存储

  • 首先,在本app有权访问的文件夹下以OpenifExist方式建立一个文件夹
1 StorageFolder MediaFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("Media", CreationCollisionOption.OpenIfExists);
  • 接下来,思考怎么对缓存到本地的图片进行命名,这里最好是使用图片原本的名字。
1 CacheImage(new Uri(MediaElement.Attributes[0].InnerText), FileName);
  • 而后,经过BackgroundDownloader以ReplaceIfExist的方式异步下载图片存储
 1 public async static void CacheImage(Uri Source, string FileName)
 2         {
 3             try
 4             {
 5                 StorageFolder MediaFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("Media", CreationCollisionOption.OpenIfExists);
 6                                                 
 7                 StorageFile destinationFile = await MediaFolder.CreateFileAsync(
 8                     FileName, CreationCollisionOption.ReplaceExisting);
 9 
10                 BackgroundDownloader downloader = new BackgroundDownloader();
11                 DownloadOperation download = downloader.CreateDownload(Source, destinationFile);
12                 await download.StartAsync();
13 
14             }
15             catch (Exception ex)
16             {
17 
18             }
19         }

 当这个图片存储完成之后,为了在断网的状况下可以访问到咱们缓存的图片,这时咱们要修改获取到的xml格式数据的content(注意这时咱们从网络获取到的xml格式数据尚未存储到本地)

四、储存咱们已经修改好的xml数据

1 var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(Name, CreationCollisionOption.ReplaceExisting);
2 var data = Content.GetXml();
3 await FileIO.WriteTextAsync(file, data);

(以前有朋友问到为何以ReplaceExisting的方式在app的安装文件夹(不是本示例中的ApplocationData文件夹)建立文件提示“拒绝访问”,由于app不像普通的桌面软件我们可以本地随意修改,微软也是为了防止app被修改以保证app的质量,更多解释能够参考这篇MSDN帖子http://social.msdn.microsoft.com/Forums/zh-CN/d8e42152-0b7b-4216-8dc9-18ae1ad152cf/storagefile#ca74e62d-d2e1-4e2f-ab8f-1f0d395fb591
五、既然xml本地缓存好了读取就很简单了,但要注意如下两个条件:

  • 咱们要肯定好多长时间更新一下缓存,超出这个时间再去访问网络更新资源
  • 当咱们要访问网络,但发现网络不可用的时候就要去访问本地存储的资源了,下面的代码来判断网络是否链接
 1 public static bool CheckConnection()
 2         {
 3             try
 4             {
 5                 string connectionProfileInfo = string.Empty;
 6                 ConnectionProfile InternetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();
 7                 if (InternetConnectionProfile == null)
 8                 {
 9                     return false;
10                 }
11                 var networkConnectivityLevel = InternetConnectionProfile.GetNetworkConnectivityLevel();
12 
13 
14                 if (
15                      networkConnectivityLevel == NetworkConnectivityLevel.LocalAccess
16                     || networkConnectivityLevel == NetworkConnectivityLevel.None)
17                 {
18                     return false;
19                 }
20                 else
21                 {
22 
23                     return true;
24                 }
25 
26             }
27             catch (Exception ex)
28             {
29                 return false;
30             }
31 
32         }

更多详细请参见源码 

(源代码连接再也不提供)

问:假如xml的图片正在下载,未下载完成,此时我就去读不就出错了吗?

答:这个问题已经考虑到,若是你的网速足够快能够不考虑这种状况。但我非要考虑这种状况,那么你可使用SemaphoreSlim,可对同时访问资源或资源池的线程数加以限制。

问:咱们知道只有在控件须要显示图片的时候图片才会被拉取,图片才会被缓存,那采用你这个方法岂不是无论控件需不须要显示图片都要去下载图片吗?

答:的确存在这种问题,这种方法最好是用在全部控件都是可见显性的状况下吧。更好的解决方法你们多多讨论。

问:我是先将获取修改好的xml数据绑定到控件好仍是先把xml存到本地再去读一次xml好呢?

答:视状况而定吧,我以为直接将修改好的xml数据绑定到控件比较好。

 

上面只是示例了对图片的缓存,固然也能缓存视频,更多问题还请你们多多发现,相互学习,共同提升。

相关文章
相关标签/搜索