2012-04-11 42 views
1

我有一个非常简单的测试与共享对象的Flex与移动我有一个人类。共享对象不能在flex工作correclty - 手机

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] ,但注释掉,,,

共享对象甚至可以正确存储对象数组。我相信持久性管理者也是一样。

回答

3

问题的根源在于您试图将实例MovieClip保存到SharedObject中。由于MovieClip是一个内部对象(原生Flash),因此无法将其转换为可以存储的表单。这会导致闪存将数据转换为存储到磁盘的通用对象。我只能猜测在这一点上到底是什么进入SharedObject。

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

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

有几个可能的解决方法,有些是:

  • 数据存储为文本
  • Store中的数据为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

非常类似于上文所描述,除了串行化处理/ deserialise方法将接受的ByteArray,其目的将写入的一个附加的参数的文本方法。 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使用相同版本的课程进行保存和加载。

希望有所帮助。

+1

第一段说明了这一切 - SharedObjects不存储基于显示的对象。还有一点要提到的是,另一种克服匿名对象限制的方法是使用[RemoteClass]元标签 - 这将自动为您应用createAlias方法,以便当它遇到与该签名相匹配的对象时,它会返回给您您期望的类的一个实例,而不仅仅是Object类型。 – 2012-04-11 14:13:20

+0

感谢您的解释和代码示例。 – james 2012-04-12 05:57:12