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數據綁定到控件比較好。

 

上面只是示例了對圖片的緩存,固然也能緩存視頻,更多問題還請你們多多發現,相互學習,共同提升。

相關文章
相關標籤/搜索