— boreal-kiss.com

[AIR] カスタムクラスオブジェクトのローカル保存

カスタムクラスオブジェクトをAIRのファイル読み書きで使用する方法(Flex環境)と注意点について。AMFのserialize/deserializeの話なのでNetConnectionなどにも応用可能だと思う。

使い方

  1. 保存したいクラスに[RemoteClass]メタタグを付ける(aliasの設定は必須ではない)。例えばcom.borealkiss.UserNameクラスを使いたい場合は以下のとおり。
    package com.borealkiss{
        
        [RemoteClass]
        public class UserName{
        }
    }
  2. ローカルで保持されるのはクラスのパブリックプロパティ(or getters/setters)のみ。例えば以下の場合だとUserName.firstNameの情報を保持したままクラスオブジェクトがローカルに保存できるようになる。publicプロパティを使う場合は以下のとおり。
    package com.borealkiss{
        
        [RemoteClass]
        public class UserName{
            public var firstName:String;
        }
    }

    getters/settersを使用する場合は以下のとおり。この場合setとget両方が定義されていないとローカル保存できない。

    package com.borealkiss{
        
        [RemoteClass]
        public class UserName{
            private var _firstName:String;
    
            public function set firstName(value:String):void{
                _firstName = value;
            }
            public function get firstName():String{
                return _firstName;
            }
        }
    }
  3. publicまたはsetters/getters定義されているクラスプロパティは全て保存される。保存したくないプロパティには[Transient]メタタグを付ける。例えばUserName.firstNameはローカル保存したいが、UserName.lastNameプロパティは保存したくない場合は以下ように記述する。
    package com.borealkiss{
        
        [RemoteClass]
        public class UserName{
            public var firstName:String;
            
            [Transient]
            public var lastName:String;
        }
    }

    getters/settersを使う場合は、get/setの定義直前に記述する。(privateプロパティ直前の記述は無効)

    package com.borealkiss{
        
        [RemoteClass]
        public class UserName{
            private var _firstName:String;
            private var _lastName:String;
            
            public function set firstName(value:String):void{
                _firstName = value;
            }
            public function get firstName():String{
                return _firstName;
            }
            
            [Transient]
            public function set lastName(value:String):void{
                _lastName = value;
            }
            public function get lastName():String{
                return _lastName;
            }
        }
    }
  4. FileStream.writeObject()でローカルファイルに保存する。以下の例ではApplicationStorageDirectory (MacだとUsers/USERNAME/Library/Preferences/APPLICATION_ID/Local_Store/)の”username.data”ファイルに書き出される(UserName.lastNameは[Transient]タグがあるので保存されない)。
    import flash.filesystem.File;
    import flash.filesystem.FileMode;
    import flash.filesystem.FileStream;
    import com.borealkiss.UserName;
    
    var user:UserName = new UserName();
    user.firstName = "Colin";
    user.lastname = "Moock";
    
    var f:File = File.applicationStorageDirectory.resolvePath("username.dat");
    var fs:FileStream = new FileStream();
    fs.open(f,FileMode.WRITE);
    fs.writeObject(user);
    fs.close();
  5. ローカルファイルからデータを取得する場合はFileStream.readObject()を使う。戻り値は型が指定されていないのでUserNameクラスにキャストする必要がある。
    var f:File = File.applicationStorageDirectory.resolvePath("username.dat");
    var result:UserName;
                
    if (f.exists){
        var fs:FileStream = new FileStream();
        fs.open(f,FileMode.READ);
        while (fs.bytesAvailable){
            result = fs.readObject() as UserName;
        }
        fs.close();
    }
    
    trace(result.firstName);//Colin
    trace(result.lastName);//null

注意点

  1. FileStream.readObject()でクラスオブジェクトを取得するとき、クラスオブジェクトのコンストラクタが(引数の設定ができないにも関わらず)必ず呼ばれる。そのためコンストラクタがデフォルト値を持たない引数を持つ場合はFileStream.readObject()を使うとエラーになる。例えば以下の場合、クラスオブジェクトはローカル保存はできるがローカルから呼び出すことができない。
    //FileStream.readObject()できない場合
    package com.borealkiss{
        
        [RemoteClass]
        public class UserName{
            public var firstName:String;
            public var lastName:String;
            
            /**
             * Constructor
             */ 
            public function UserName(firstName:String,lastName:String){
                this.firstName = firstName;
                this.lastName = lastName;
            }
        }
    }

    コンストラクタが引数を持たないか、または引数にデフォルト値が設定されている場合は大丈夫。

    //FileStream.readObject()できる場合
    package com.borealkiss{
        
        [RemoteClass]
        public class UserName{
            public var firstName:String;
            public var lastName:String;
            
            /**
             * Constructor
             */ 
            public function UserName(firstName:String="",lastName:String=""){
                this.firstName = firstName;
                this.lastName = lastName;
            }
        }
    }
  2. FileStream.readObject()ではコンストラクタが呼ばれた後、ローカル保存されている値がプロパティに設定される。
0 comments
Submit comment