Save Application state on Disk or some where so us

2019-07-04 08:32发布

问题:

In flex builder 4.5 i'm working on a project like cacoo. I want to save diagrams(display object,ui components,text) before close the application into somewhere than I would be able to access after the application open again.

more clear:-If user edit some uml diagram on this project and save it for edit later and close application.after some days he/she want to edit previously saved diagram. now how i'm save this diagram for future edit.

回答1:

If save/open dialog will work for you, you can yse FileReference API. Before doing this, you have to implement serialization/deserialization of your state into/from String/ByteArray/XML object.

private var fileReference:FileReference;

// due to security restrictions, this method must be called from an
// event handler that responds to a user event (mouse click or key
// press), otherwise it will fail.

private function saveState(serializedState:*, fileName:String):void {
    fileReference = new FileReference();

    fileReference.addEventListener(Event.COMPLETE, onSaved);
    fileReference.addEventListener(IOErrorEvent.IO_ERROR, onSavingError);

    try {
        fileReference.save(serializedState, fileName); // will open save dialog
    } catch (e:Error) {
        trace("error saving data: " + e.toString());
        freeListeners();
    }
}

private function onSaved(e:Event):void {
    trace("saved!");
    freeListeners();
}

private function onSavingError(e:ErrorEvent):void {
    trace("error saving data: " + e.toString());
    freeListeners();
}

private function freeListeners():void {
    fileReference.removeEventListener(Event.COMPLETE, onSaved);
    fileReference.removeEventListener(IOErrorEvent.IO_ERROR, onSavingError);
}

Similarly with restoring the state (use FileReference.browse(), then FileReference.load()).

If you need to save/restore app state without any dialogs, then you should probably use AIR (or SharedObject, as Raja Jaganathan suggested). But it seems to be not the case, as you want the user to be able to re-open the diagram in another system. To achieve this, you should allow the user to save his work to the appropriate place, so later he can move it to another machine/system and re-open it with your application.

Another alternative is to store everything on the server and provide the user with a list of saved files (like Cacoo does). If you go this way, you'll have to implement the corresponding server-side API. It may be REST API or smth like RTMP server. In the case of REST API, use FileReference.upload() to upload the data to your server, and URLLoader.load() to obtain it back.



回答2:

You can store your diagram state through SharedObject for better you create one class which hold all of your state of Diagram so that later you can use

SharedObject using http://livedocs.adobe.com/flex/3/html/help.html?content=lsos_5.html

you can use registerClassAlias for custom class stored in sharedobject.

myClassInstance = new MyClass();
myClassInstance.x = 100;
myClassInstance.y = 100;
myClassInstance.text = "diagrams";

registerClassAlias("com.path.to.MyClass", MyClass);
myStuff = SharedObject.getLocal("myAppStuff");
myStuff.data.whatINamedIt = myClassInstance;
myStuff.flush();

now when get it back out... you can say:

myStuff = SharedObject.getLocal("myAppStuff");
var mySavedClass:MyClass = myStuff.data.whatINamedIt as MyClass;

Read mySavedClass instance value then inject to your diagram model when open again.

To implement application close event

http://www.flexer.info/2007/10/25/fabridge-warn-on-flex-application-exit/



回答3:

Sprite or MovieClip other DisplayObject objects can not be direct serialized. So you should stored objects information (origin x,y, width, height, color, child info...). using a ByteArray or Array or Dictionary ... and that save to ShareObjects. later roll back from ShareObject and re-create Original Object. MovieClip or Sprite appropriate purpose is container.

Here is my test code.

1. create a Movieclip. purpose is container.

2. draw a rectangle using a graphics. And set the coordinates.

var drawWidth:Number = 500;
var drawHeight:Number = 300;

var rect:MovieClip = new MyRect();
rect.graphics.beginFill(0xffffff*Math.random(),1);
rect.graphics.drawRect(0,0,drawWidth,drawHeight);
rect.graphics.endFill();
rect.x= 300;
rect.y= 100;

3. Stores the information in the array.

var myRectInformation:Array = new Array();
myRectInformation.push(rect.x);
myRectInformation.push(rect.y);
myRectInformation.push(drawWidth);
myRectInformation.push(drawHeight);
var bmd:BitmapData = new BitmapData(rect.width, rect.height,true,0);
bmd.draw(rect);
//is byteArray.
myRectInformation.push(bmd.getPixels(new Rectangle(0,0,bmd.width,bmd.height)));

4. save to SharedObjects, array.

var mySaveData:SharedObject = SharedObject.getLocal("myStorage")
mySaveData.data.myRectInformation = myRectInformation;
mySaveData.flush();

5. this is load from SharedObject data stored. and recreate Objects.

var rect:MovieClip = new MyRect();
var loadBmd:BitmapData = new BitmapData(mySaveData.data.myRectInformation[2], mySaveData.data.myRectInformation[3], true, 1);
loadBmd.setPixels(new Rectangle(0,0,loadBmd.width,loadBmd.height), mySaveData.data.myRectInformation[4]);
var bmp:Bitmap = new Bitmap(loadBmd);
rect.addChild(bmp);
rect.x = mySaveData.data.myRectInformation[0];
rect.y = mySaveData.data.myRectInformation[1];
addChild(rect);