23.6.对象序列化

23.6.1.问题
我想对自定义对象进行序列化并保存到硬盘驱动器的文件中。
23.6.2.解决办法
通过class-alias注册自定义类,使用ActionScript Message Format (AMF) 编码序列化对象,并使用FileStream.writeObject方法把对象存储到文件上。
23.6.3.讨论
使用AIR文件系统API,你可以把经过AMF编码序列化过的对象写入文件流缓冲区中。

ActionScript语言中大多数内建对象类型比如String和Boolean都自动支持序列化。这些类型同通过AMF被编码为二进制格式,当经过反序列化可以恢复原来的值。然而自定义对象是不自动支持序列化的,要启动自定义对象序列化支持,你需要用registerClassAlias 方法用一个类别名注册此类,或者在类定义前申明这个[RemoteClass]元数据标签。

假定你的程序要把用户信息作为一个对象进行显示,可过一段时间被同一个程序或者被其他程序载入,这些程序应已知道如何处理该对象,要表现用户信息的自定义对象看起来大概是下面这样:
+展开
-ActionScript
package com.oreilly.flexcookbook {
[RemoteClass]
[Bindable]
public class UserData {
public var firstName:String;
public var lastName:String;
public var age:Number;
public var sessionLength:Number;
public function UserData( firstName:String = "",lastName:String = ""){
this.firstName = firstName;
this.lastName = lastName;
}
}
}

每次你的程序被用户打开时,一个新的UserData对象被创建,等待用户输入信息,通常可以保存这些信息以特定的格式保存到文本文件上,但是你也可以序列化对象到文件上,从而可轻易的以对象类型读取,不必要解析字符串,重置UserData新实例属性。要序列化对象且通过反序列化保留其属性值,需要使用[RemoteClass]元数据标签注册它。

在类申明前插入[RemoteClass] 元数据标签,可启动此类在使用AMF序列化和反序列化中能保持类型信息和属性值。你也可以在变量定义前加上[Transient]元数据标签,指示此变量不会被序列化。比如上面例子中的sessionLength属性每次程序运行时都会更新,因为没必要进行保存,你可以把此属性标记为transient属性拒绝被序列化:
+展开
-ActionScript
package com.oreilly.flexcookbook {
[RemoteClass]
public class UserData {
public var firstName:String;
public var lastName:String;
public var age:Number;
[Transient]
public var sessionLength:Number;
public function UserData( firstName:String = "",lastName:String = ""){
this.firstName = firstName;
this.lastName = lastName;
}
}
}

使用FileStream.writeObject方法把序列化自定义对象写到文件里,当使用writeObject和readObject 写入和读取二进制数据默认所用的编码格式是AMF 3 规范。通过设置FileStream.objectEncoding属性,你可以使用AMF 0 格式,下面的例子保存用户信息到扩展名为.user的文件上:
+展开
-XML
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxmllayout="vertical">
<mx:Script>
<![CDATA[
import com.oreilly.flexcookbook.UserData;
private var userData:UserData = new UserData();
private static const EXT:String = ".user" ;
private function submitHandler():void {
userData.firstName = firstField.text;
userData.lastName = lastField.text;
userData.age = ageField.value;
saveUserData();
}
private function saveUserData():void
{
var fnm:String = userData.firstName + "_"+userData.lastName + EXT;
var file:File =File.desktopDirectory.resolvePath( fnm );
var stream:FileStream = new FileStream();
stream.open( file, FileMode.WRITE );
stream.writeObject( userData );
stream.close();
}

]]>
</mx:Script>
<mx:Form>
<mx:FormItem label="First Name:">
<mx:TextInput id="firstField"
change="{submitBtn.enabled = firstField.text != ''}"/>

</mx:FormItem>
<mx:FormItem label="Last Name:">
<mx:TextInput id="lastField"
change="{submitBtn.enabled = lastField.text != ''}"/>

</mx:FormItem>
<mx:FormItem label="Age:">
<mx:NumericStepper id="ageFieldminimum="18maximum="110" />
</mx:FormItem>
<mx:Button id="submitBtnlabel="submitenabled="falseclick="submitHandler();" />
</mx:Form>
</mx:WindowedApplication>

当用户输入并提交信息后,submitHandler事件处理器被调用,UserData对象被更新,接着调用saveUserData方法。在saveUserData方法中,用UserData实例的firstName和lastName属性组成文件路径,文件被保存到桌面上,扩展名为.user。当反序列化时,文件被再次打开,对象属性值将被会恢复。下面的例子扩展了之前的程序,提供对打开.user文件的支持:
+展开
-XML
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxmllayout="vertical">
<mx:Script>
<![CDATA[
import com.oreilly.flexcookbook.UserData;
[Bindable]
private var userData:UserData = new UserData();
private var file:File = File.desktopDirectory;
private var filter:FileFilter = new FileFilter("User File""*.user");
private static constEXT:String = ".user";
private function submitHandler():void{
userData.firstName = firstField.text;
userData.lastName = lastField.text;
userData.age = ageField.value;
saveUserData();
}
private function saveUserData():void {
var fnm:String = userData.firstName + "_" + userData.lastName + EXT;
var file:File = File.desktopDirectory.resolvePath( fnm );
var stream:FileStream = new FileStream();
stream.open( file, FileMode.WRITE );
stream.writeObject( userData );
stream.close();
}
private function openHandler():void {
file.browseForOpen( "Open User", [filter] );
file.addEventListener( Event.SELECT, selectHandler );
}
private function selectHandler( evt:Event ):void {
var stream:FileStream = new FileStream();
stream.open( file, FileMode.READ );
userData = stream.readObject();
}

]]>
</mx:Script>
<mx:Form>
<mx:FormItem label="First Name:">
<mx:TextInput id="firstField"
text="{userData.firstName}"
change="{submitBtn.enabled = firstField.text != ''}"/>

</mx:FormItem>
<mx:FormItem label="Last Name:">
<mx:TextInput id="lastField"
text="{userData.lastName}"
change="{submitBtn.enabled = lastField.text != ''}"/>

</mx:FormItem>
<mx:FormItem label="Age:">
<mx:NumericStepper id="ageFieldvalue="{userData.age}minimum="18maximum="110" />
</mx:FormItem>
<mx:Button id="submitBtnlabel="submitenabled="falseclick="submitHandler();"
/>

</mx:Form>
<mx:HRule width="100%" />
<mx:Button label="openclick="openHandler();" />
</mx:WindowedApplication>

当用户点击open按钮时,File.browseForOpen方法会打开一个对话框,并设置了过滤器只显示.user 扩展名的文件。当一个文件被选中后, selectHandler 方法被调用, 通过FileStream.readObject方法将文件读入到缓冲区,readObject方法将反序列化UserData对象,通过数据绑定将保存的数据显示到表单。

FileStream.writeObject和FileStream.readObject方法提供了很多方法用于序列化数据对象到文件系统上。通过[RemoteClass]元数据标签注册类即可用AMF将类进行编码为二进制格式。

如果你是从文本文件中处理载入和解析键--值对自定义对象,那么序列化自定义对象将大大减少开发开销。

加支付宝好友偷能量挖...


评论(0)网络
阅读(81)喜欢(0)flash/flex/fcs/AIR