首页 > 代码库 > Win8.1应用开发之离线缓存

Win8.1应用开发之离线缓存

我们在开发应用商店应用时,需要app具有缓存的功能,这样在离线模式下,仍能工作。我们选择的project为Hub。

这里采取的策略是:在HubPage.xaml.cs(之所以不选择App.xaml.cs,是为了能让用户一边操作界面一边进行下载)中,利用await异步编程,避免阻塞UI,先读取存有图片路径的JSON,然后解析该JSON得到每一张图片的URI,再根据URI下载图片,对于文字资源,直接下载JSON。这里要特别注意文件操作——文件权限,同时更要注意文件流的选取——如果选择不当会导致在下载图片时偶然性僵死。

在HubPage.xaml.cs中:

using Bing.Maps;
using demo02.Common;
using demo02.Data;
using demo02.DataModel;
using demo02.DataStructure;
using demo02.Entity;
using demo02.Helper;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using WhereWeGo.Helper;
using Windows.ApplicationModel.Search;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Storage;
using Windows.UI;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Navigation;

//“中心页”项模板在 http://go.microsoft.com/fwlink/?LinkID=321224 上有介绍

namespace demo02
{

    public sealed partial class HubPage : Page
    {

        //一个容器,里面存有每个图片的url对象
		//将JSON中存的图片的uri读取到PicArray,然后通过PicArray下载图片
        private static OfflinePicArray PicArray { get; set; } 

        private NavigationHelper navigationHelper;
        private ObservableDictionary defaultViewModel = new ObservableDictionary();


        public HubPage()
        {
            this.InitializeComponent();
            this.navigationHelper = new NavigationHelper(this);
            this.navigationHelper.LoadState += navigationHelper_LoadState;

        }

 
        private async void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
        {

            if (ConnectState.isConnected) //如果网络是连接的,进行缓存下载
            {
                if (OfflineFirstFlag.isFirstEnter) //由于之后会多次进入HubPage页面,我们只应当在第一次进入页面时进行下载
                {
                    OfflineFirstFlag.isFirstEnter = false;

					//获得图片资源,先下载存有uri的JSON,再解析JSON,再通过解析出的uri下载图片
					
                    //获取存有用于离线模式下图片uri的JSON
                    await HttpGetOfflinePICSJSON();

                    //获取存有老师和地域图片的url的JSON
                    await HttpGetOfflineTeacherRegionJSON();

                    //获得第一部分图片
                    await HttpGetOfflingPicByUrl();

					//获得第二部分图片
                    await HttpGetOfflingPicByUrl02();

					//获得第三部分图片
                    await HttpGetOfflingPicByUrl03();

					//获得第四部分图片
                    await HttpGetOfflingPicByUrl04();

					
					//获得文字资源
                    //获得离线模式数据展示的来源JSON
                    await HttpGetOfflineJSON();
                }
            }
        }


        //向服务器请求最新的PICS JSON

        private async static Task HttpGetOfflinePICSJSON()
        {
            XDownload xmen = new XDownload(ServiceUrl.URL_OFFLINE_PICSJSON, XDownload.App, OfflineSubFolder.Name, ServiceUrl.PICSJSON_LOCALNAME);
            await xmen.GetDataAsync();
        }

        private async static Task HttpGetOfflingPicByUrl()
        {

            try {
                StorageFolder storageFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
                StorageFolder folder = await storageFolder.GetFolderAsync(OfflineSubFolder.Name);
                StorageFile storageFile = await folder.GetFileAsync(ServiceUrl.PICSJSON_LOCALNAME);

                if (storageFile != null)
                {
                    XDownload bigOverhead = new XDownload();
                    bigOverhead.Library = XDownload.App;
                    bigOverhead.Myfolder = OfflineSubFolder.Name;

                    // 获取指定的文件中的文本内容
                    string textContent = await FileIO.ReadTextAsync(storageFile, Windows.Storage.Streams.UnicodeEncoding.Utf8);

                    PicArray = JsonConvert.DeserializeObject<OfflinePicArray>(textContent);

                    foreach (OfflinePicUri onePic in PicArray.Images)
                    {
                        foreach (string picName in onePic.ShowImages)
                        {
                            if (picName != null)
                            {
                                bigOverhead.Uri = ServiceUrl.BASEURL_OFFLINE + onePic.ImageFolder + picName;

                                System.Diagnostics.Debug.WriteLine(bigOverhead.Uri + "kakakakakakkakakak");

                                bigOverhead.Filename = picName;
                                await bigOverhead.GetDataAsync();
                            }
                        }

                    }
     
            } catch(Exception ex) {
                
            }          
        }


        private async static Task HttpGetOfflingPicByUrl02()
        {
            try
            {
                StorageFolder storageFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
                StorageFolder folder = await storageFolder.GetFolderAsync(OfflineSubFolder.Name);
                StorageFile storageFile = await folder.GetFileAsync(ServiceUrl.PICSJSON_LOCALNAME);

                if (storageFile != null)
                {
                    XDownload bigOverhead = new XDownload();
                    bigOverhead.Library = XDownload.App;
                    bigOverhead.Myfolder = OfflineSubFolder.Name;

                    // 获取指定的文件中的文本内容
                    string textContent = await FileIO.ReadTextAsync(storageFile, Windows.Storage.Streams.UnicodeEncoding.Utf8);

                    PicArray = JsonConvert.DeserializeObject<OfflinePicArray>(textContent);

                    foreach (OfflinePicUri onePic in PicArray.Images)
                    {
                        if (onePic.TileImagePath != null)
                        {
                            bigOverhead.Uri = ServiceUrl.BASEURL_OFFLINE + onePic.ImageFolder + onePic.TileImagePath;
                            bigOverhead.Filename = onePic.TileImagePath;
                            await bigOverhead.GetDataAsync();
                        }
                    }

                }
            }
            catch (Exception ex) {
                
            }        
        }



        private async static Task HttpGetOfflingPicByUrl03()
        {

            try {
                StorageFolder storageFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
                StorageFolder folder = await storageFolder.GetFolderAsync(OfflineSubFolder.Name);
                StorageFile storageFile = await folder.GetFileAsync(ServiceUrl.PICSJSON_LOCALNAME);

                if (storageFile != null)
                {
                    XDownload bigOverhead = new XDownload();
                    bigOverhead.Library = XDownload.App;
                    bigOverhead.Myfolder = OfflineSubFolder.Name;

                    // 获取指定的文件中的文本内容
                    string textContent = await FileIO.ReadTextAsync(storageFile, Windows.Storage.Streams.UnicodeEncoding.Utf8);

                    PicArray = JsonConvert.DeserializeObject<OfflinePicArray>(textContent);

                    foreach (OfflinePicUri onePic in PicArray.Images)
                    {
                        if (onePic.Badge != null)
                        {
                            bigOverhead.Uri = ServiceUrl.BASEURL_OFFLINE + onePic.ImageFolder + onePic.Badge;
                            bigOverhead.Filename = onePic.Badge;
                            await bigOverhead.GetDataAsync();
                        }
                    }

                }
            } catch(Exception ex) {
                
            }         
        }

        private async Task HttpGetOfflingPicByUrl04()
        {
            try {
                StorageFolder storageFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
                StorageFolder folder = await storageFolder.GetFolderAsync(OfflineSubFolder.Name);

                //接着下载老师和地域的图片
                StorageFile storageFile01 = await folder.GetFileAsync(ServiceUrl.T_R_JSON_LOCALNAME);

                if (storageFile01 != null)
                {

                    XDownload bigOverhead = new XDownload();
                    bigOverhead.Library = XDownload.App;
                    bigOverhead.Myfolder = OfflineSubFolder.Name;

                    // 获取指定的文件中的文本内容
                    string textContent = await FileIO.ReadTextAsync(storageFile01, Windows.Storage.Streams.UnicodeEncoding.Utf8);

                    TRPic tr = new TRPic();

                    tr = JsonConvert.DeserializeObject<TRPic>(textContent);

                    foreach (string onePic in tr.TeacherImages)
                    {

                        //开始下载图片       

                        bigOverhead.Uri = ServiceUrl.BASEURL_OFFLINE + onePic;

                        bigOverhead.Filename = TeaRegFilter.GetPicName(onePic);

                        await bigOverhead.GetDataAsync();

                    }

                }
            }catch (Exception ex) {
                
            }

        }

        private async static Task HttpGetOfflineJSON()
        {

            XDownload xmen = new XDownload(ServiceUrl.URL_OFFLINE_JSON, XDownload.App, OfflineSubFolder.Name, ServiceUrl.JSON_LOCALNAME);

            await xmen.GetDataAsync();
        }

        private async static Task HttpGetOfflineTeacherRegionJSON()
        {
		
            XDownload xmen = new XDownload(ServiceUrl.URL_OFFLINE_TEACHER_REGION_JSON, XDownload.App, OfflineSubFolder.Name, ServiceUrl.T_R_JSON_LOCALNAME);

            await xmen.GetDataAsync();
        }


    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Windows.Networking.BackgroundTransfer;
using Windows.Storage;
using Windows.Storage.Streams;

namespace demo02.Helper
{

    //该类的作用是将服务器端的文件uri通过http下载到本地指定目录,并命名
    public class XDownload
    {

        public static string Documents = "Documents";
        public static string Pictures = "Pictures";
        public static string Music = "Music";
        public static string Videos = "Videos";
        public static string App = "App"; 

        public XDownload()
        {
            this.Uri = "";
            this.Library = "";
            this.Myfolder = "";
            this.Filename = "";
        }

        public XDownload(String uri, String library, String myfolder, String filename)
        {
            this.Uri = uri;
            this.Library = library;
            this.Myfolder = myfolder;
            this.Filename = filename;
        }

        //不带返回值的Task
        public async Task GetDataAsync()
        {

            StorageFolder folder = null;
            try
            {
                switch (this.Library)
                { 
                    case "Documents":
                        folder = KnownFolders.DocumentsLibrary;
                        break;
                    case "Pictures":
                        folder = KnownFolders.PicturesLibrary;
                        break;
                    case "Music":
                        folder = KnownFolders.MusicLibrary;
                        break;
                    case "Videos":
                        folder = KnownFolders.VideosLibrary;
                        break;
                    case "App":
						folder = Windows.ApplicationModel.Package.Current.InstalledLocation; //C:\Users\tom\Documents\GitHub\wherewegov1\wherewego\demo02\bin\Debug\AppX
						break;
                    default:
                        System.Diagnostics.Debug.WriteLine("ERROR: Make sure you are using the four special library: Documents, Music, Videos, Pictures");
                        return;
                }

                if (this.Myfolder == "")
                {
                    System.Diagnostics.Debug.WriteLine("ERROR: Make sure you input a valid subfolder");
                    return;
                }

                StorageFolder childFolder = await folder.CreateFolderAsync(this.Myfolder, CreationCollisionOption.OpenIfExists);    

                if (this.Filename == "")
                {
                    System.Diagnostics.Debug.WriteLine("ERROR: Make sure you input a valid filename");
                    return;
                }

                //Creates a new file in the current folder, and specifies what to do if 
                //a file with the same name already exists in the current folder.
                StorageFile outputFile = await childFolder.CreateFileAsync(this.Filename, CreationCollisionOption.ReplaceExisting);

              
				//选择恰当的流,避免下载图片过程中僵死
				var fs = await outputFile.OpenAsync(FileAccessMode.ReadWrite);
                HttpClientHandler handler = new HttpClientHandler();
                handler.ClientCertificateOptions = ClientCertificateOption.Automatic;
                HttpClient hc = new HttpClient(handler);
                HttpResponseMessage response = await hc.GetAsync(this.Uri, HttpCompletionOption.ResponseHeadersRead);
                Stream stream = await response.Content.ReadAsStreamAsync();
                IInputStream inputStream = stream.AsInputStream();
                ulong totalBytesRead = 0;
                while (true)
                {
                    // Read from the web.  
                    IBuffer buffer = new Windows.Storage.Streams.Buffer(1024);
                    buffer = await inputStream.ReadAsync(
                        buffer,
                        buffer.Capacity,
                        InputStreamOptions.None);

                    if (buffer.Length == 0)
                    {
                        // 完成  
                        break;
                    }

                    // 进度  
                    totalBytesRead += buffer.Length;
                    System.Diagnostics.Debug.WriteLine("Bytes read: {0}", totalBytesRead);

                    // 写文件.  
                    await fs.WriteAsync(buffer);
                }
                inputStream.Dispose();
                fs.Dispose();  
				
            }
            catch (Exception)
            {
                System.Diagnostics.Debug.WriteLine("ERROR: file download failed, tai can le");
            }

        }

        public string Uri { get; set; }
        public string Library { get; set; }
        public string Myfolder { get; set; }
        public string Filename { get; set; } 
    }
}