3

モバイルアプリ開発は初めてですが、モバイルRPGゲームのキャラクターシートアプリを作成しようとしています。SQLiteを使用する代わりに、アプリが中断またはシャットダウンされたときにPersistenceManagerを使用して文字データを永続化しようとしていますが、正しく使用されているかどうかはわかりません。これが私がこれまでに持っているものです。

Main.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:ViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                        xmlns:s="library://ns.adobe.com/flex/spark" firstView="views.CharactersView" 
                        applicationDPI="160" persistNavigatorState="true">

</s:ViewNavigatorApplication>

CharactersView.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" creationComplete="creationCompleteHandler(event)">

<fx:Script>
    <![CDATA[
        import mx.collections.ArrayCollection;
        import mx.events.FlexEvent;

        protected function creationCompleteHandler(event:FlexEvent):void
        {
            var o:Object = new Object();
            o.name = "Aragorn";
            o.type = "Ranger";
            o.strength = 97;
            o.speed = 7;
            Database.insertCharacter(o);
            trace(Database.characters.length);
        }

    ]]>
</fx:Script>

<s:List id="list" width="100%" height="100%"/>

Database.as:

import spark.managers.PersistenceManager;

public class Database
{
    private static var data:Array = [];
    private static var pm:PersistenceManager = new PersistenceManager();

    public static function get characters():Array
    {
        if (!pm.load() || pm.getProperty("characters") == null)
        {
            Database.data = [];
        }
        else
        {
            Database.data = pm.getProperty("characters") as Array;
        }
        return data;
    }

    public static function insertCharacter(o:Object):void
    {
        Database.data.push(o);
        pm.setProperty("characters", Database.data);
        pm.save();
    }

}

CharactersView.mxmlのcreationCompleteハンドラーで、文字の挿入が機能するかどうかをテストするために、任意の情報を使用して1回限りの文字を作成しています。これを完全にそのまま実行するたびに、traceステートメント(配列の長さ)は1を返します。実行するたびに1ずつ上がるべきではありませんか?これは何かが正しくないことを示していますが、persistencemanagerがデータを適切に保存していないのですか?pm.save()がtrueを返すかどうかを確認する必要がありますか?もしそうなら、イベントをディスパッチしてから、トレースステートメントを実行して適切な長さを取得する必要がありますか?一部のデータを保存するだけでは非常に複雑に見えるので、何が起こっているのか、どのように修正するのか完全にはわかりません。

いずれにせよ、私が尋ねているのは、私の現在の設定が正しいかどうかです。正しくない場合、誰かが簡単な例を持っていますか、またはpersistencemanagerを適切に使用する方法について私のコードに基づいて簡単な例を作成できますか?

このテクニックを習得したら、他のいくつかのアプリも作成できるので、これを理解したいと思っています。前もって感謝します!

編集:私はPMに関してすべてを正しく使用しているようで、受け取った回答はアプリを機能させるのに役立ちました。しかし、前進すると、私のアプリはおかしな動作を始めました。たとえば、私のリストは、他のほとんどのコンポーネントと同様に、相互作用に対して非常にゆっくりと反応するようです。以下の新しいコード。

Main.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:ViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                        xmlns:s="library://ns.adobe.com/flex/spark" firstView="views.CharactersView" 
                        applicationDPI="160" persistNavigatorState="true">

</s:ViewNavigatorApplication>

CharactersView.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" creationComplete="creationCompleteHandler(event)">

<fx:Script>
    <![CDATA[
        import mx.collections.ArrayCollection;
        import mx.events.FlexEvent;

        protected function creationCompleteHandler(event:FlexEvent):void
        {
            update();
        }

        private function update():void
        {
            title = "D&D Characters (" + Database.characters.length + ")";
            list.dataProvider = new ArrayCollection(Database.characters);
        }

        protected function button1_clickHandler(event:MouseEvent):void
        {
            var vo:CharacterVO = new CharacterVO();
            vo.name = "Aragorn";
            vo.className = "Ranger";
            vo.race = "Human";
            vo.level = 6;
            vo.gender = "Male";
            vo.alignment = "Unaligned";
            vo.hp = 25;
            vo.xp = 100;
            Database.insertCharacter(vo);
            update();
        }

    ]]>
</fx:Script>

<s:actionContent>
    <s:Button label="+" click="button1_clickHandler(event)"/>
</s:actionContent>

<s:List id="list" width="100%" height="100%"/>

</s:View>

Database.as:

import spark.managers.PersistenceManager;

public class Database
{
    private static var data:Array = [];
    private static var pm:PersistenceManager = new PersistenceManager();

    public static function get characters():Array
    {
        return data;
    }

    public static function insertCharacter(o:CharacterVO):void
    {
        Database.data.push(o);
        pm.setProperty("characters", Database.data);
        pm.save();

        if (!pm.load() || pm.getProperty("characters") == null)
        {
            Database.data = [];
        }
        else
        {
            Database.data = pm.getProperty("characters") as Array;
        }
    }

}

CharacterVO.as:

import flash.utils.IDataInput;
import flash.utils.IDataOutput;
import flash.utils.IExternalizable;

public class CharacterVO implements IExternalizable
{
    public var name:String;
    public var className:String;
    public var race:String;
    public var gender:String;
    public var alignment:String;
    public var level:Number;
    public var hp:Number;
    public var xp:Number;


    public function writeExternal(output:IDataOutput):void {
        output.writeUTF(name);
        output.writeUTF(className);
        output.writeUTF(race);
        output.writeUTF(gender);
        output.writeUTF(alignment);
        output.writeFloat(level);
        output.writeFloat(hp);
        output.writeFloat(xp);
    }

    public function readExternal(input:IDataInput):void {
        name = input.readUTF();
        className = input.readUTF();
        race = input.readUTF();
        gender = input.readUTF();
        alignment = input.readUTF();
        level = input.readFloat();
        hp = input.readFloat();
        xp = input.readFloat();
    }
}

ご覧のとおり、ほとんどのコードは私が最初に投稿したものと同じです。CharacterVOクラスを追加し、CharactersView.mxmlでいくつかを移動し、PersistenceManager読み込みコードをinsertCharacter関数に移動しました(このように、新しいアイテムが追加されるたびにのみPMを読み込み、呼び出すたびにではありません) Database.characters)。

繰り返しになりますが、私のアプリはインタラクションに対して非常にゆっくりと反応するようですが、まったく反応しない場合もあります。何かが正しくありません。これまでモバイルアプリでこの問題が発生したことはありません。配列をPMに格納してから、それをリストのdataProviderとして設定しようとすると、問題が発生する可能性がありますか?

4

1 に答える 1

0

私はこれを使用することにあまり慣れていませんが、ドキュメントからは、IExternalizableを実装しているとは思わないため、おそらく汎用オブジェクトを使用できないようです。ドキュメントによると、これは何らかの理由でエラーを引き起こしませんが、それらのオブジェクトを実際に読み書きすることはできません。

http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/managers/PersistenceManager.html

マネージャを使用して値を保存する場合、すべての値を共有オブジェクトに適切に書き込むことができることが重要です。クラスまたは非標準のフラッシュプリミティブを格納する複雑なオブジェクトは、正しく機能するためにflash.net.IExternalizableインターフェイスを実装する必要があります。互換性のないオブジェクトを保存してもRTEは発生しませんが、データが読み戻されるときに未定義の動作が発生します。

これを自分で使用するとき、プロジェクトで別のSOポスターを支援したとき、保存/取得したモデルオブジェクトのプロパティを変更した場合を除いて、実際に問題が発生したことを思い出せません。ローカル共有オブジェクトを手動で吹き飛ばす必要がありました。それ以外の方法で作成すると、逆シリアル化できませんでした(意味がありますが、注意する必要があります)。IExternalizableを実装したことを実際に覚えていませんが、他の人がそれを行った可能性があります。

これを試して:

[CharacterVO.as]

public class CharacterVO implements IExternalizable
{
    public var name:String;
    public var type:String;
    public var strength:Number;
    public var speed:Number;


    public function writeExternal(output:IDataOutput) {
        output.writeUTF(name);
        output.writeUTF(type);
        output.writeFloat(strength);
        output.writeFloat(speed);
    }

    public function readExternal(input:IDataInput) {
        name = input.readUTF();
        type = input.readUTF();
        strength = input.readFloat();
        speed = input.readFloat();
    }
}

次に、ジェネリックオブジェクトを作成する代わりに、そのVOのインスタンスを作成します。Arrayは、すべての要素を順番にシリアル化することで自動的にシリアル化されると思います。

于 2012-07-31T18:34:38.940 に答える