How to deserialize array collection in flex - actionscript-3

I am stuck with an issue:
In which I am serializing an array collection to a file, the array collection has two type of items an Image and a class object.
It serialize successfully, but when I de-serialize it, It simply returns array collection of objects and I found my self unable to convert these objects into Images and the class object(this class is defined by myself and having three members, two images and a shape).
I am adding the code which I used:
[Bindable] var objcnvs:ClassCanvas;
protected function btnSave_clickHandler(event:MouseEvent):void
{
//for saving data serializaion
var arrAllSave:ArrayCollection = new ArrayCollection();
for(var i:int = 0;i<arrAll.length; i++)
{
try
{
var tempCon:ConnectImage = arrAll[i];
arrAllSave.addItem({item:arrAll[i], type:"ConnectImage" });
}
catch(er:Error)
{
var tempImage:Image = arrAll[i];
var objImage:ClassImage = new ClassImage(arrAll[i]);
arrAllSave.addItem({item:objImage, type:"Image" });
}
}
// First, generate your ByteArray from the VO.
var byteArray : ByteArray = new ByteArray();
byteArray.writeObject( arrAll );
// Resolve your file location.
//var file : File = File.applicationStorageDirectory.resolvePath( "testFile.ri" );
var mapName:String = txtMapTitle.text;
var file : File = File.applicationStorageDirectory.resolvePath( 'Saved Maps/'+mapName+'.imm' );
if(file.exists == true)
{
lblWarn.text = "Map already Exists. Please enter Defferent Map Title";
}
else if(mapName == "")
{
lblWarn.text = "Please enter a title for Map.";
}
else
{
var fileStream:FileStream = new FileStream();
// Save the file to the given location.
fileStream.open(file, FileMode.WRITE);
fileStream.writeBytes( byteArray );
fileStream.close();
lblWarn.text = "Map Saved successfully";
}
}
protected function btnLoadMap_clickHandler(event:MouseEvent):void
{
// Execute the file load.
var loadFileName:String = "t1";
var request : URLRequest = new URLRequest ( "app-storage:/"+"Saved Maps/"+loadFileName+".imm" );
var receptor : URLLoader = new URLLoader( request );
// Make sure our content is interpreted as a ByteArray.
receptor.dataFormat = URLLoaderDataFormat.BINARY;
receptor.addEventListener( Event.COMPLETE, fileLoadedHandler );
}
private function fileLoadedHandler ( event : Event ) : void
{
// Retrieve the event target, cast as the URLLoader we just created
var loader : URLLoader = event.target as URLLoader;
// Retrieve the loaded data. We know it's a ByteArray, so let's cast it as well.
var data : ByteArray = loader.data as ByteArray;
// Use the ByteArray.readObject method to reconstruct the object.
var obj : Object = data.readObject();
// Cast the object and assign it to our data container.
var loadArrAll:ArrayCollection = obj as ArrayCollection;
}
The last line
var loadArrAll:ArrayCollection = obj as ArrayCollection;
this is the issue. I get the array collection but it has only a list of objects no images and no my class objects (although these are there but I found no way to convert this array collection in previous form when I serialized it.)

class that needs to be serialized/deserialised needs to implement flash.utils.IExternalizable.
public function readExternal(input:IDataInput):void - here you restore object
public function writeExternal(output:IDataOutput):void - here you saving object
best regards

Zain, you have to declare your classes like that:
package com
{
[RemoteClass]
public class myClass
{
public function myClass()
{
}
}
}

Related

Can not retrieve data from completely Loaded static variable AS3

Basically I was trying to read an image in binary with help of URLLoader() and convert it to a image again in flash.
I wrote 2 static methods that one of them read image and set data properties to binary and other one is the COMPLETE handler.
In COMPLETE handler I convert the binary data to ByteArray and assign it to a static variable. then tried to access to it from Main Timeline but it won't work.
The problem is my temporary variable not fully loading the static variable and when I'm checking BytesAvailable it's something like only 2.
What I'm doing wrong?
The COMPLETE handler:
public static function compHand(e:Event):void
{
var myByteArray:ByteArray = URLLoader(e.target).data as ByteArray;
LoaderToObject.ImageBytes = myByteArray;
trace(myByteArray.bytesAvailable);
if (LoaderToObject.ImageBytes.length != myByteArray.length)
{
trace(myByteArray.length);
trace(LoaderToObject.ImageBytes.length);
}
else
{
trace("successFully loaded!");
}
}
public static function loadBin(FileUrl:String)
{
var imageBytes:ByteArray=new ByteArray();
var binUrl:URLRequest = new URLRequest(FileUrl);
var binLoader:URLLoader = new URLLoader(binUrl);
binLoader.dataFormat = URLLoaderDataFormat.BINARY;
binLoader.addEventListener(Event.COMPLETE,compHand);
//trace(LoaderToObject.ImageBytes);
trace(FileUrl);
}
The function I used in main timeLine:
function loadfile(e:MouseEvent):void
{
LoaderToObject.loadBin("chick.bmp");//send file to URLLoader
imageBytes= LoaderToObject.ImageBytes;
MakeImage2(imageBytes);
}
Please help me
Because URLLoader is asynchronous, so When you try to access imageBytes, the imageBytes hasn't been load complete yet.
Your need to pass callback function to loadBin for been called when load complete
Here is an example
The load class
Class MyLoader {
private var callback:function;
private var binLoader:URLLoader;
public function load(FileUrl:String, $callback:Function):void
{
callback = $callback;
//your code
var imageBytes:ByteArray=new ByteArray();
var binUrl:URLRequest = new URLRequest(FileUrl);
binLoader = new URLLoader(binUrl);
binLoader.dataFormat = URLLoaderDataFormat.BINARY;
binLoader.addEventListener(Event.COMPLETE,compHand);
//trace(LoaderToObject.ImageBytes);
trace(FileUrl);
}
private function compHand(e:Event):void
{
var myByteArray:ByteArray = URLLoader(e.target).data as ByteArray;
if (callback != null)
{
callback(myByteArray, this);
}
}
}
LoaderToObject's load function
//make MyLoader class live, it's important
private var loadValidDic:Dictionary = new Dictionary();
public static function loadBin(FileUrl:String, callback:Function)
{
var loader:MyLoader = new MyLoader();
loadValidDic[loader] = callback;
loader.load(FileUrl, internalComplete);
}
private static function internalComplete(ba:ByteArray, loader:MyLoader):void
{
var callback:function = loadValidDic[loader];
if (callback)
{
callback(ba);
loadValidDic[loader] = null;
delete loadValidDic[loader];
}
}
Used in timeline
function loadfile(e:MouseEvent):void
{
LoaderToObject.loadBin("chick.bmp", onComplete);//send file to URLLoader
}
private function onComplete(imageBytes:ByteArray):void
{
MakeImage2(imageBytes);
}

Flex - saving Serialized ArrayCollection of Objects to File

Creating class with RemoteClass metateg
[RemoteClass]
public class Result
{
public function Result(){}
}
Function for writing in file
public function writeData(object:Object):void
{
var file:File = File.desktopDirectory.resolvePath("data.txt");
if (file.exists)
file.deleteFile();
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeObject(object);
fileStream.close();
}
Function for reading from file
public function readData():Object
{
var file:File = File.desktopDirectory.resolvePath("data.txt");
if(!file.exists)
return 0;
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.READ);
var obj:Object = fileStream.readObject();
fileStream.close();
return obj;
}
Function when application initializing
public function initApplication():void
{
writeData(new Result()); // write object to file.
var result:Result = readData() as Result; // create Result class object and initializing it data from file
var array:ArrayCollection = new ArrayCollection(); // create collection and fill it objects of Result class
array.addItem(new Result());
array.addItem(new Result());
array.addItem(new Result());
writeData(array); // writing collection in file
var arr:ArrayCollection = readData() as ArrayCollection; // initializing new collecion of collection from file.
}
Here is the problem. Returned collection with objects of Object type.
How can I get collection of Result type objects?
Bad way below
for each (var object:Object in arr)
{
object = object as Result;
}
Use registerClassAlias() before serialization/deserialization

AS3 Event Handler stuck in infinite loop

I have a problem with my event handler. I am trying to use URLRequest to load some data from a database. But it's stuck in an infinite loop. Any suggestion of why is it looping, even after all the data is loaded?
The result is pushed into an array.
Code:
public function Listingdetailinfo()
{
somedata = SearchVectorTest.lists;
SrSend = new URLRequest("http://testurl/requestimage.php");
SrSend.method = URLRequestMethod.POST;
Arvariables = new URLVariables ;
SrSend.data = Arvariables;
SaLoader = new URLLoader();
SaLoader.dataFormat = URLLoaderDataFormat.TEXT;
Arvariables.data1 = somedata[0];
SaLoader.load(SrSend);
SaLoader.addEventListener(Event.COMPLETE,Asandler);
function searchVOs( pic:String )
{
this.pic = pic;
}
function Asandler(event:Event):void
{
trace(event.target.data);
// retrieve data from php call
var resultString:String = event.target.data;
trace(event.target.data);
// parse result string as json object and cast it to array
var resultArray:Array = JSON.parse(resultString) as Array;
var len:int = resultArray.length;
trace(resultString);
// create vector of SearchVO
var searchVOs:Array = new Array();
// get the length of the result set
var i:int;
for (i=0; i<len; i++)
{
searchVOs[i] = new Listingdetailinfo();
searchVOs[i].pic = resultArray[i].pic;
myArray.push(searchVOs[i].pic);
}
}
}
I assume your code represents the constructor of Listingdetailinfo class. The reason of your "infinite loop" is that you are creating new instances of this class in
searchVOs[i] = new Listingdetailinfo();

how to read the data from the JSP in a MXML through actionscript?

We are collecting the data at run time in Collection object in JSP page. We want to read this data from the JSP in a MXML through actionscript.
pls share the sample if you have.
thanks,
Sudarshan
function loadData():void
{
var ldr:URLLoader = new URLLoader();
var request:URLRequest = new URLRequest("page.jsp");
ldr.addEventListener(Event.COMPLETE, onLoad);
ldr.load(request);
}
private function onLoad(e:Event):void
{
var ldr:URLLoader = URLLoader(e.target);
trace(ldr.data);//traces the loaded string
//if the data is xml
/*
var myxml:XML = new XML(ldr.data);
trace(myxml.toXMLString());
*/
//update: answer to the comment:
//If the input string just lacks a root tag from being valid xml,
//you can introduce a dummy root tag.
var myxml:XML = new XML("<root>" + ldr.data + "</root>");
trace(myxml.data.toString()); //Hello
trace(myxml.value.toString()); //Hi
}
page.jsp should serialize the collection to appropriate format (xml/json/whatever) and return it.

Passing Informaton for Files with Loader

I'm using Loader to get the image data out of a ByteArray. The problem is that I need to store that image data with a name (which is known beforehand) once it's passed to the complete handler. Since the operation is asynchronous, I can't be sure which image of multiple will finish loading first, so it seems I need to pass the information with it somehow... I can't seem to find any properties of Loader that pass any vaguely useful information along.
Any recommendations on how I might accomplish this?
Couldn't you just use the Loader.name property?
var ldr:Loader = new Loader();
ldr.name = 'name_of_the_loader';
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderListener);
ldr.loadBytes(aByteArray);
...
function loaderListener(event:Event):void {
trace('name of the completed loader is '+LoaderInfo(event.target).loader.name);
}
Could you provide some code?
private var loaders:Array = [];
private var names:Array = [];
//inside loadImages method
for(i = 0; i < len; i++)
{
var ldr:Loader = new Loader();
//add listeners and call load
loaders.push(ldr)
names.push(name-of-ith-image);
}
private function onLoadComplete(e:Event):void
{
var index:Number = loaders.indexOf(LoaderInfo(e.target).loader);
var requiredName:String = names[index];
trace(requiredName);
}
First solution would be to use a Dictionary to map the Loader instances to names.
Like this:
private var names : Dictionary = new Dictionary();
...
var ldr : Loader = new Loader();
names [ ldr ] = 'someName';
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderListener);
ldr.loadBytes(aByteArray);
...
function loaderListener(event:Event):void {
trace('name of the completed loader is '+ names[ event.target ] );
}
The other solution would be to use a functor, like this:
var ldr : Loader = new Loader();
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, createListener( 'someName' ) );
ldr.loadBytes(aByteArray);
...
function createListener( imgName : String ) : Function {
return function ( event : Event ) : void {
trace('name of the completed loader is '+ imgName );
}
}
loader.contentLoaderInfo.url will be having URL of the loaded image (e.g http://sometURL/image1.jpg).