移动开发中的数据处理需要传统应用程序开发人员采取不同的思维方式。比如,对于许多移动应用程序而言,当用户关闭或切换应用程序、接听来电,以及其他原因导致程序强制关闭时,保存用户数据尤为重要。另外,由于移动应用程序的视图经常被销毁和重建,您需要考虑如何在视图之间处理数据。因此,您需要在两种情况下保存数据:
●应用程序执行时(指的是关闭和重启应用程序时)
●应用程序视图切换
本文将给出处理这些情况的几种方法。
运用destructionPolicyattribute处理视图之间的数据
在解决视图切换之间数据存储问题之前,理解视图的生命期是很重要的。在Flex4.5中任何时候只允许有一个视图是活动的。默认情况下,其他视图都会被销毁,等到需要时再重建。这一行为由视图类(View class)的destructionPolicy的属性控制,该属性默认值是自动(auto)。如果您将属性值设为从不(never),视图将被缓存,保持状态直至通过调用navigator.popView()重新激活。
请看图1中的流程图。默认情况下(或是您将destructionPolicy的属性值明确设为“自动”),当把视图B推送到堆栈中时,视图A将被销毁,当把视图C推送到堆栈中时,视图C将被销毁。一旦视图A或视图B之上的视图出栈了,则将重建视图A或视图B。当您设定视图A和视图B的destructionPolicy属性值为“从不”,则这两个视图失效,被缓存,但不被销毁,新视图被推送。随后,当它们之上的视图出栈时,又可以轻易地将它们激活。
图1 在Flex4.5中创建和销毁视图
需要注意的是,即便您设定某一视图的destructionProperty为“从不”,只要调用pushView(),该视图仍会被激活,重新显示。只有当最上面的视图出栈了,缓存才生效,显示出之前的视图。请看图2的流程图。第二次推送视图B时,它被重建,之前的数据将无法访问(除非您采用其他办法保持或恢复数据。)
图2 第二次推送视图B将导致视图重建
我开发过一个应用程序,以视图1为开始,并调用pushView()激活视图2。默认情况下(不设定任何destructionPolicy属性值)的正常事件顺序可以从我插入应用程序中的跟踪语句看出:
1. 对屏幕变化作出响应,视图1被移除(removing事件)
2. 视图2被添加至显示列表(added事件)
3. 视图2添加事件(add事件)
4. 视图2创建完成(creatioComplete事件)
5. 视图1失效(viewDeactive事件)
6. 视图1被移除出显示列表(removed事件)
7. 视图2被激活(viewActivate事件)
利用数据属性处理视图之间的数据
另一个保存视图之间数据的选项(在我看来这一选项更直观)是利用视图对象(Viewobject)的数据属性。该属性会把数据的状态保存在内存中,因此当您通过推送或出栈的方式返回至视图时,可以访问数据。您可以在数据属性中设定任意类型的对象,包括自定义类。下面给出的Person类的范例中,数据属性被设定到一个值对象(value object)。需要注意的是,视图显示之前,视图中的数据属性已实例化并就绪,无需担心数据属性不可用。
您还可以通过在视图上重写createReturnObject()方法来获得出栈视图返回的数据。如果您的应用程序展示的是视图A且您推送视图B,您可以通过在视图B重写createReturnObject(),将视图B返回的数据传递至视图A;比如:
|
本范例中,person是我在ActionScript中定义的一个类:
package model
{
[Bindable]
public class Person
{
public var person_id:int;
public var userid:String;
public var password:String;
public var fname:String;
public var lname:String;
public var city:String;
}
}
一旦返回至视图A,您可以访问返回的对象,方法如下:
|
由于对象类型实际是ViewReturnObject,您必须明确定义对象属性才能获得该值。
程序执行时保存数据
您有多种办法可以在应用程序执行时保存数据,这样即便应用程序在关闭后重新启动了,数据仍可访问。Flex 4.5有内置的存储机制,通过ViewNavigatorApplication 或TabbedViewNavigatorApplication上名为persistNavigatorState的属性进行访问。在您将persistNavigatorState的值设为“真”来启动该机制后,您可以侦听navigatorStateLoading和navigatorStateSaving事件,并对事件作出必要的处理。如果您想开发自己的个性化存储法,您可以调用事件处理器中的preventDefault()。
使用该技巧时,您的根应用程序标签会同如下类似:
|
/Applications/Adobe Flash Builder4.5/sdks/4.5/frameworks/projects/mobilecom
当您设定persistNavigatorState为“真”,您的应用程序将自动保存视图及数据的状态到名为FXAppCache的共享对象(shared object)。如果您观察Flex 4.5 SDK的原始码PersistenceManager.as(在我的苹果电脑上,该文件路径为/Applications/AdobeFlash Builder4.5/sdks/4.5/frameworks/projects/mobilecomponents/src/spark/managers),您会发现该变量是如何产生的:
在Flash Builder模拟器里运行您的应用程序后,您可以通过找到硬盘上的本地共享对象(localshared object)来查看所保存的内容。在我的苹果电脑上,该文件路径为/Users/hollyschinsky/Library/Preferences/DataPersistence.debug/LocalStore/#SharedObjects/ DataPersistence.swf/ FXAppCache.sol.
![](http://hi.csdn.net/attachment/201109/28/0_1317188554VUqq.gif)
如果需要保存自定义类,如上述例子中的Person类,您必须侦听主应用程序(main application)中的preinitialize 事件并且注册类的别名;比如:
|
如果您将persistNavigatorState属性值设为真,则数据将自动保存,但如果您想要增加更多属性或访问persistencemanager,您可以使用ViewNavigatorApplication或者 TabbedViewNavigatorApplication persistenceManager对象;比如:
|
如果您通过视图来访问它,则会看见:
|
![](http://hi.csdn.net/attachment/201109/28/0_1317188660JkMo.gif)
图4 调试器中的persistenceManager 变量
您会发现默认保存了两个额外属性——versionNumber 和 navigatorState,用以还原视图至之前的状态。
使用默认PersistenceManager的弊端是数据并没有加密。但是,您可以利用IPersistenceManager接口自由地定义一个存储机制。因此您可以进行本地存储加密,以获得和设定敏感数据。另外一个小的弊端是,某些情况下,该机制只适合小量的数据。如果您有大量数据需要保存,则应选择SQLite。如果想要阅读关于构建写入SQLite数据库的移动应用程序,可以参考Christophe Coenraets的Buildinga mobile employee directory sample with Flex and Flash Builder。