2012-04-11 63 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