1

我有一个非常简单的测试,使用移动设备的 flex 共享对象我有一个 person 类。

package
{
    import flash.display.MovieClip;


    public class Person extends MovieClip
    {
        var personsname:String="";
        public function Person(name:String)
        {
            personsname = name;
        }
    }
}

然后在视图中添加一些简单的代码。

    var person1:Person;
                var person2:Person;
                var person3:Person;
                var person4:Person;
                var thePeople:Array=[];
                var so:SharedObject;
                function init():void{
                person1 = new Person("james");
                person2 = new Person("mike");
                person3 = new Person("Amanda");
                person4 = new Person("Shelly");
                thePeople.push(person1,person2,person3,person4);
                    //so = SharedObject.getLocal("savedData"); //clear it again
                ///so.clear(); // clear it again
                savePeople();
                getPeople();
                }

                private function savePeople():void{
                    so = SharedObject.getLocal("savedData");
                    if(so.data.thePeopleArray == null){
                        so.data.thePeopleArray = thePeople;
                        so.flush();
                    }
                }


                private function getPeople():void{
                    so = SharedObject.getLocal("savedData");
                    var thePeeps:Array = so.data.thePeopleArray;
                    trace(thePeeps);
            }

我第一次运行它时,它会追踪 [object Person]4 次我关闭模拟器并重建并运行它

,,,

如果我清除它,它会[object Person]再次显示,但注释掉得到,,,

共享对象甚至可以正确存储对象数组。我相信的persistanceManager也是如此。

4

1 回答 1

3

这里问题的根源是您试图将实例 MovieClip 保存到 SharedObject 中。由于 MovieClip 是一个内在对象(原生于 flash),它不能转换为可以存储的形式。这会导致闪存将数据转换为存储到磁盘的通用对象。我现在只能猜测到底是什么进入了 SharedObject 中。

它似乎是第一次工作,因为 flash 实际上并没有在 getPeople() 调用中加载共享对象,它只是使用已经在内存中的对象。应用程序第二次运行时,它会从磁盘读取通用对象并创建一个通用对象。

还有一个问题是,Flash 播放器在读取对象时不知道将数据传递给构造函数。

有一些可能的解决方法,其中一些是:

  • 将数据存储为文本
  • 将数据存储为 ByteArray
  • 将数据存储在“数据对象”中

这些中的每一个都需要在读写过程中进行一些转换,但这可以使用接口来简化。这也增加了灵活性,以防您的对象发生更改,您仍然能够读取 SharedObject 中的数据。

1:文字

例如,您可以向Person对象添加两个方法,分别调用它们serialise()deserialise(). 该serialise()方法将返回可以存储在共享对象中的文本。将deserialise()解析文本并填充对象的值。

这是一个示例来说明这一点:

class Person {
    private var name:String;
    private var age:int;

    public function serialise():String {
        return [name, age].join("\t");
    }

    public function deserialise(input:String):void {
        var tokens:Array = input.split("\t");
        name = tokens[0];
        age = parseInt(tokens[1]);
    }

    public static function create(name:String, age:int):Person
    {
        var output:Person = new Person();
        output.name = name;
        output.age = age;
        return output;
    }
}

为了便于使用,我们可以创建一个类来管理人员集合:

class People {
    private var people:Vector.<Person> = new Vector.<Person>();

    public function clear():void {
        people.splice(0, people.length);
    }

    public function add(person:Person):void {
        people.push(person);
    }

    public function serialise():String {
        var output:Array = [];

        for each (var person:Person in people)
            output.push(person.serialise());

        return output.join("\n");
    }

    public function deserialise(input:String):void {
       var tokens:Array = input.split("\n");

       for each (var token:String in tokens) {
           var person:Person = new Person();
           person.deserialise(token);
           add(person);
       }
    }

    public function save():void {
        var so:SharedObject = SharedObject.getLocal("cookie");
        so.data.people = serialise();
        so.flush();
    }

    public function load():void
    {
        var so:SharedObject = SharedObject.getLocal("cookie");

        if (so.data.people != null)
            deserialise(so.data.people);
    }
}     

用法:

var people:People = new People();
people.load();
trace(people.serialise());

people.clear();
people.add(Person.create("Candy", 21));
people.add(Person.create("Sandy", 23));
people.add(Person.create("Randy", 27));
people.save();
trace(people.serialise());

此示例中的一个明显缺陷是 \n 和 \t 字符不能用作数据的一部分(即用于人名)。这是文本数据的常见缺点。

** 更新:查看内置JSON方法以获得将对象序列化到文本和从文本序列化的一致方法。

2:字节数组

非常类似于上面描述的文本方法,除了序列化/反序列化方法将接受一个字节数组的附加参数,对象将写入该参数。然后将从共享对象中保存和加载 ByteArray。这种方法的优点是生成的数据通常比文本方法紧凑且通用。

Flash 还定义了可以在此处使用的IDataInputIDataOutput接口。

3:数据对象

如果您仍然更喜欢直接存储对象,那么您可以创建一个代理对象,其唯一目的是承载数据。数据对象(又名 DO)是一个只有变量而没有方法的对象。例如:

class PersonDO {
    public var name:String;
}

它会像这样使用:

            var person2:Person;
            var person3:Person;
            var person4:Person;
            var thePeople:Array=[];
            var so:SharedObject;
            function init():void{
            person1 = new Person("james");
            person2 = new Person("mike");

            // store the people data into data objects
            person1DO = new PersonDO();
            person1DO.name = person1.name;

            person2DO = new PersonDO();
            person2DO.name = person2.name;

            thePeople.push(person1DO,person2DO);
            savePeople();

            // load the people into data objects
            getPeople();
            person1 = new Person(thePeople[0].name);
            person2 = new Person(thePeople[1].name);

            private function savePeople():void{
                so = SharedObject.getLocal("savedData");
                if(so.data.thePeopleArray == null){
                    so.data.thePeopleArray = thePeople;
                    so.flush();
                }
            }


            private function getPeople():void{
                so = SharedObject.getLocal("savedData");
                var thePeeps:Array = so.data.thePeopleArray;
                trace(thePeeps);
        }    

尽管这可能看起来比其他方法更简单,但直接存储对象也有缺点: - 存储的数据非常脆弱 - 如果您更改对象,那么您的数据将变得不可用,除非您有每个对象的多个版本。- 您需要确保将对数据对象的引用编译到应用程序中。- 共享对象的一个​​常见使用场景是从一个 SWF 保存数据对象,然后将它们加载到另一个 SWF 中。您需要确保两个 SWF 使用相同版本的保存和加载的类。

希望有帮助。

于 2012-04-11T10:59:25.447 回答