如何序列化Vector。<customobject>?

时间:2015-10-29 18:43:10

标签: actionscript-3 object serialization

http://jacksondunstan.com/articles/1642我跟着这个到了T,但我遇到了问题。我试图保存一堆图标。他们有一个定制的班级&#34; Iconn&#34;并存储在Vector.<Iconn>中以备将来使用。一旦用户添加了新图标,我就会打开一个文件流并用它来编写整个矢量。

        public function addShortcut(f:File):void
    {
        //Display on side
        icons.reverse(); //Add to the front so it displays on the top.
        icons.push(new Iconn(f)); //Use 16x16 bitmap

        addChild(icons[icons.length - 1]);
        icons.reverse();

        //Save object
        fs = new FileStream();
        fs.open(shortcuts, FileMode.WRITE);
        fs.writeObject(icons);
        fs.close();

        reorder(); //Reorganizes the icons on the screen.
    }

这一切都很好,没有任何错误,但当我尝试重新启动应用程序并保存一些图标时,矢量甚至不存在。

    icons = new Vector.<Iconn>();
    if (shortcuts.exists)
    {
        trace("Shortcuts exist..adding");
        fs = new FileStream();
        fs.open(shortcuts, FileMode.READ);
        icons = fs.readObject() as Vector.<Iconn>;
        fs.close();
        trace("icons = " + icons); //TypeError: Error #1009: Cannot access a property or method of a null object reference.
        trace("icons length  = " + icons.length); //TypeError: Error #1009: Cannot access a property or method of a null object reference.
    }

我尝试添加registerClassAlias("Vector.<Iconn>", Vector.<Iconn>);,但后来我遇到编译错误 1067: Implicit coercion of a value of type __AS3__.vec:Vector.<Iconn> to an unrelated type Class

编辑:这是我的Iconn课程http://pastebin.com/5TujzpvR

1 个答案:

答案 0 :(得分:2)

这有几个原因无效。

  1. 当对象被反序列化时,您无法将参数传递给它们的构造函数。这意味着您需要取出嵌套在对象中的所有类的所有构造函数参数,或者通过赋予它们默认值使它们全部是可选的。

  2. 您必须注册在序列化对象中使用的每个单个非基本类(包括对象的类本身)。这包括嵌套类。在您的情况下,这至少包括:

    flash.display.Bitmap;
    flash.display.Sprite;
    flash.events.MouseEvent;
    flash.filesystem.File;
    fl.transitions.Tween;
    fl.transitions.easing.Strong;
    

    加上这些类中引用的任何内容。

  3. 序列化显示对象不起作用*(技术上可以使用实现IExternalizable的自定义类,但它非常复杂)。如果您想要一个示例,则有一个here

  4. 序列化显示对象的最佳方法是创建一个非常非常基本的类,其中包含重建显示对象所需的最小数据。

    在您的情况下,看起来您真正需要的只是位图数据。所以你可以创建一个简单的类,如下所示:

    package 
    {
        import flash.geom.Rectangle;
        import flash.utils.ByteArray;
    
        public class SaveData 
        {
            public var imgBytes:ByteArray;
            public var bounds:Rectangle;
            public var transparent:Boolean;
        }
    }
    

    它存储的全部是原始位图数据(像素值的字节数组)和位图的边界。

    首先,您需要注册所有使用的类。这看起来像这样:

            //you need to register your class that you're using writeObject on
            registerClassAlias("SaveData", SaveData); 
    
            //you also need to register the two classes that are referenced in your SaveData class
            registerClassAlias("flash.utils.ByteArray", ByteArray);
            registerClassAlias("flash.geom.Rectangle", Rectangle);
    
            //you ALSO need to register Point since it's referenced inside the Rectangle class
            registerClassAlias("flash.geom.Point", Point);
    

    现在,为了保存它,主要做你正在做的事情:

    //create a vector to store your list of items to save
    var saveArray:Vector.<SaveData> = new Vector.<SaveData>();
    
    //loop through all your icons and do the following in the loop (where bitmap is the icon's bitmap):
    
    var saveData:SaveData = new SaveData();
    saveData.bounds = bitmap.getBounds(bitmap);
    saveData.imgBytes = bitmap.bitmapData.getPixels(saveData.bounds);
    saveData.transparent = bitmap.bitmapData.transparent;
    saveArray.push(saveData);
    
    //write the Vector to the file
    fs = new FileStream();
    fs.open(shortcuts, FileMode.WRITE);
    fs.writeObject(saveArray);
    fs.close();
    

    现在,当你准备好把它全部加载回来时:

    fs = new FileStream();
    fs.open(shortcuts, FileMode.READ);
    var saveArray:Vector.<SaveData> = fs.readObject() as Vector.<SaveArray>;
    fs.close();
    
    //now loop through your array and re-create all your icons.
    
    for(var i:int=0;i<saveArray.length;i++){
        var bmd:BitmapData = new BitmapData(saveArray[i].bounds.width, saveArray[i].bounds.height, saveArray[i].transparent);
        bmd.setPixels(saveArray[i].bounds, saveArray[i].imgBytes);
    
        var bitmap:Bitmap = new Bitmap(bmd);
    
        //instead of passing in a file to your Iconn class, tweak it so you pass in a bitmap:
        var icon:Iconn = new Iconn(bitmap);
    
        //do what you need to do with he icon
    }