16.1 概述 Windows Phone提供了XML、Isolated Storage、WebServices、 Cloud等数据访问方式,这一章我们来介绍Isolated Storage。另外我们我们将结合应用程序的生命周期介绍IsolatedStorageSettings,最后我们来说明一下Windows Phone对SDCARD的处理方式以及关于Isolated Storage的一个常见误解。
16.2 IsolatedStorage Windows Phone 7都有自己的永久存储空间,叫做isolated storage,程序可以用过System.IO.IsolatedStorage名称空间中提供的类来访问。Isolated storage中的文件可以读写。本节,我们通过一个删除目录的方法来学习IsoatedStorage是的使用方法。
首先,创建一个Silverlight应用程序,在MainPage构造函数加入如下代码
- InitializeComponent();
- IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
- try
- {
- if (!isf.DirectoryExists("Directory1"))
- isf.CreateDirectory("Directory1");
- if (!isf.FileExists("Directory1/File1"))
- {
- IsolatedStorageFileStream isoStream1 = new IsolatedStorageFileStream("Directory1/File1", System.IO.FileMode.Create, isf);
- isoStream1.Dispose();
- }
- if (isf.FileExists("Directory1/File1"))
- Debug.WriteLine("Directory1/File1 created!");
- isf.DeleteDirectory("Directory1");
- }
- catch (IsolatedStorageException e)
- {
- Debug.WriteLine(e.ToString());
- }
从Visual Studio Ouput窗口我们可以看到Directory1目录生成了,但是调用DeleteDirectory(“Directory1”)失败了,抛出了异常 An error occurred while accessing IsolatedStorage.
发生这个异常的原因是,如果文件夹不是空的,不能调用IsolatedStorageFile的DeleteDirectory直接删除。
我们来修改一下程序,定义一个DeleteDirectory成员函数,代码如下
- public static void DeleteDirectory(IsolatedStorageFile store, String root)
- {
- String dir = root;
- // delete file in current dir
- foreach (String file in store.GetFileNames(dir + "/*"))
- {
- store.DeleteFile(dir + "/" + file);
- }
- // delete sub-dir
- foreach (String subdir in store.GetDirectoryNames(dir + "/*"))
- {
- DeleteDirectory(store, dir + "/" + subdir + "/");
- }
- // delete current dir
- store.DeleteDirectory(dir);
- }
MainPage()函数代码如下
- InitializeComponent();
- IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
- try
- {
- if (!isf.DirectoryExists("Directory1"))
- isf.CreateDirectory("Directory1");
- if (!isf.FileExists("Directory1/File1"))
- {
- IsolatedStorageFileStream isoStream1 = new IsolatedStorageFileStream("Directory1/File1", System.IO.FileMode.Create, isf);
- isoStream1.Dispose();
- }
- if (isf.FileExists("Directory1/File1"))
- Debug.WriteLine("Directory1/File1 created!");
- DeleteDirectory(isf, "Directory1");
- if (!isf.FileExists("Directory1/File1"))
- Debug.WriteLine("Directory1/File1 removed!");
- }
- catch (IsolatedStorageException e)
- {
- Debug.WriteLine(e.ToString());
- }
- isf.Dispose();
- }
从Debug output窗口可以看到,File1创建成功了,而且File1也被成功删除了。 我们可以在调用DeleteDirectory这行设置一个断点,然后利用Windows Phone Device Manager来看看文件系统中是否已经存在了Directory1目录和File1文件,顺便了解一下所谓的IsolatedStorage目录在哪里。如果你是第一次听到Windows Phone Device Manager的话,请参考第一章第6小节
如上图所示,在手机的\Application\Data\017174D3-EFTB-42DA-D810-58ET570E3649\Data\IsolatedStore下可以看到Directory1目录,Directory1目录下有一个File1文件。 我们打开Visual Studio按F5继续执行,再观察Windows Phone Device Manager,可以看到文件夹Directory1和它下面的文件File1确实被删除了。
希望大家能借助这么一个简单的例子了解一下IsolatedStorage实现原理 我们这里再简单说一下自定义的DeleteDirectory成员函数的原理: 如果一个目录下的文件不是子目录,那么就直接删除掉,如果是子目录递归调用DeleteDirectory删除子目录。如果任何一级目录为空则调用IsolatedStorageFile的DeleteDirectory成员函数删除目录。
16.3 IsolatedStorageSettingsIsolated Storage不但提供了文件相关操作支持,还提供了IsolatedStorageSettings类,用来保存应用程序状态信息,我们在第三章中介绍工程结构的时候曾经涉及到应用程序的生命周期,打开任何一个工程的App.xaml文件,你会看到以下代码
- Launching="Application_Launching" Closing="Application_Closing"
- Activated="Application_Activated" Deactivated="Application_Deactivated"/>
其中PhoneApplicationService可以用来保存暂时状态,程序一旦退出状态信息就会丢失,它还是我们设置程序状态变换时间处理的地方。 应用程序启动时候会产生Lauching事件,我们会通过Application_Launching处理函数得到通知;当用户按下Windows键后,用户会从当前应用程序离开,这个过程叫TombStone,这时候产生Deactivated事件;如果用户这时候再按一下返回键(左箭头按键),这时候会产生Activated事件,该应用程序开始恢复;如果用户启动引用程序后直接按返回键,这时候该应用程序就会退出,会产生Closing事件;所有这些事件如同Launching事件一样,程序可以选择性处理。 一般应用程序退出或者发生状态变换的时候我们希望保存一下数据,比如用户正在玩一个游戏,当他返回程序的时候,他希望能接着玩,而不是重新开始,这时候就需要程序根据程序状态不同提供保存和恢复功能,而IsolatedStorageSettings则可以达到这一目的。
首先,我们为App.xaml.cs添加两个成员函数
- void LoadSettings()
- {
- IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
- String value;
- settings.TryGetValue("setting1", out value);
- }
- void SaveSettings()
- {
- IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
- settings["setting1"] = "value1";
- settings.Save();
- }
在Application_Launching、Application_Activated、Application_Deactivated、Application_Closing添加上LoadSettings或者SaveSettings
- // Code to execute when the application is launching (eg, from Start)
- // This code will not execute when the application is reactivated
- private void Application_Launching(object sender, LaunchingEventArgs e)
- {
- LoadSettings();
- }
- // Code to execute when the application is activated (brought to foreground)
- // This code will not execute when the application is first launched
- private void Application_Activated(object sender, ActivatedEventArgs e)
- {
- LoadSettings();
- }
- // Code to execute when the application is deactivated (sent to background)
- // This code will not execute when the application is closing
- private void Application_Deactivated(object sender, DeactivatedEventArgs e)
- {
- SaveSettings();
- }
- // Code to execute when the application is closing (eg, user hit Back)
- // This code will not execute when the application is deactivated
- private void Application_Closing(object sender, ClosingEventArgs e)
- {
- SaveSettings();
- }
我们再次打开Windows Phone Device Manager,看看IsolatedStorageSettings是怎么实现的
从图中我们可以看到只是在IsolatedStore目录下创建了一个_ApplicationSettings文件而已,那这个文件什么样呢,我们把文件Copy到PC上看一看,它的内容如下:
- setting1
- value1
有Android或者iOS经验的开发者可能多少有点似曾相识的感觉,因为Android中的Shared Preference还有iOS的plist都可以用来保存设置信息,而且都是xml结构的。
16.4 SDCARD 访问的方式是作为内部存储的一部分,也就是不是作为特殊的外部存储访问,没有办法单独访问SDCARD。一个程序只能访问自己的IsolatedStorage。
16.5 关于Isolated Storage的一个常见误解 我们随便创建一个Silverlight工程,在工程中创建一个Images文件夹,Images下随便放一个图片文件Building.png,Windows Phone开发初学者经常误以为Images目录和Building.png都是存在Isolated Storage下的,其实不然。我们通过Windows Phone Device Manager来看一下手机上的目录结构:
从上图可以看到Building实际上是放在了程序的安装目录下\Applications\Install\3B3C8541-378A-4FD3-BD66-92AC20645BC5\Install\Images,而程序的Isolated Storage目录一般是不在程序的安装目录下,而是在\Applications\ Data目录下,我们这个例子的具体路径为\Applications\Data\3B3C8541-378A-4FD3-BD66-92AC20645BC5\Data。