October 11th, 2007 by Kyle
Tags: externalizable-interface, Flash Player, flash.net.registerclassalias(), flash.utils.iexternalizable, Flex, local-shared-object, locally-shared-object, lso, mxmlc, remoteclass, serialization, storage
Posted in: ActionScript, Flash Player, Flex
I had seen references describing how to do this, but hadn’t seen a complete example, so I whipped this one up for a customer.
Using RemoteClass metadata triggers code gen in in the compilter to ensure that the class is registered with the VM before the application can use it, this includes receiving it from a network request. The only case in which this could be a problem is if it was being used with remoting and there wasn’t a corresponding server class that also implemented the flash.utils.IExternalizable interface.
Externalizable interface doesn’t effect the ability to be serialized in AS3, it just provides customization of what gets serialized. Generally it is only used to serialize private data or hide public data from serialization. Marking the class with [RemoteClass] is what allows the typed serialization of the object (again just mxmlc code gen at the right point using the registerClassAlias() method).
There aren’t any issues, at least none that we have hit, with LSO storage and custom serialization using IExternalizable. As long as the SWF that is retrieving the data from the LSO has the IExternalizable classes linked in and registered (potentially with a “dummy variable”) then I don’t know of any reason why that wouldn’t work.
The real work behind the scenes is done by using flash.net.registerClassAlias() and it is documented (although hard to find) at:
http://livedocs.adobe.com/flex/201/html/lsos_087_3.html
Browse the source of this example.
Download a zipfile containing the source to this sample.
Here is the code for the simple app:
<mx:application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
xmlns="*" viewSourceURL="wp-content/code/Flex2.0.1hf2/739stl_LSO_Serialize_Class/srcview/index.html">
<mx:script>
<!–[CDATA[
import mx.controls.Alert;
private var so:SharedObject;
[Bindable]–> public var test:MyClass;
private function clearLSO():void {
so = SharedObject.getLocal("testData","/");
so.clear();
}
private function getLSO() :void {
so = SharedObject.getLocal("testData", "/");
var b:ByteArray = (so.data.test as ByteArray)
if(b){
b.position=0;
var o:Object = b.readObject();
test = MyClass(o);
n.text=test.name;
p.text=test.price.toString();
ta.text=test.toString();
}
else{
Alert.show("LSO testData does ot exist!");
}
}
private function setLSO():void {
so = SharedObject.getLocal("testData", "/");
var b:ByteArray = new ByteArray();
b.writeObject(test);
so.data.test=b;
so.flush();
}
private function createNewMyClass():void{
test= new MyClass(n.text);
test.price=parseFloat(p.text);
var o:Object=new Object();
o.upper=n.text.toUpperCase();
o.lower=n.text.toLowerCase();
o.psqrd=parseFloat(p.text)*parseFloat(p.text);
test.properties=o;
ta.text=test.toString();
}
private function clearInput():void{
n.text="";
p.text="";
ta.text="";
}
]]>
</mx:script>
<mx:button click="getLSO()" label="getLSO">
<mx:button click="setLSO();clearInput();" label="setLSO" enabled="{(n.text.length>0 ? p.text.length>0: false)}">
<mx:button click="clearLSO()" label="clearLSO">
<mx:button click="createNewMyClass()" label="create New MyClass">
enabled="{(n.text.length>0 ? p.text.length>0: false)}"/>
<mx:form>
<mx:formitem label="Name:">
<mx:textinput id="n">
</mx:textinput>
<mx:formitem label="Price:">
<mx:textinput id="p">
</mx:textinput>
</mx:formitem>
<mx:textinput id="ta" width="200" height="200" editable="false">
</mx:textinput>
</mx:formitem></mx:form></mx:button></mx:button></mx:button></mx:button></mx:application>
Here is the class that I am serializing and storing in the LSO:
import flash.utils.IExternalizable;
import flash.utils.IDataInput;
import flash.utils.IDataOutput;
[Bindable]
[RemoteClass(alias="MyClass")]
public class MyClass implements IExternalizable {
public function MyClass(name:String=null) {
this.name = name;
}
public var name:String;
public var properties:Object;
public var price:Number;
public function readExternal(input:IDataInput):void {
name = input.readUTF();
properties = input.readObject();
price = input.readFloat();
}
public function writeExternal(output:IDataOutput):void {
output.writeUTF(name);
output.writeObject(properties);
output.writeFloat(price);
}
public function toString():String{
var str:String=
"name: " + name + "\n"
+ "price: " + price.toString() + "\n"
for (var n:String in properties){
str+= "properties[" + n + "]: " + properties[n].toString() + "\n"
}
return str;
}
}
}
Tweet
1 Comment »

October 8th, 2008 at 12:37 pm
Very helpful!
Thanks,
Alberto