Flash Builder Mobile, правильно ли используете PersistenceManager?

Я новичок в разработке мобильных приложений, но я пытаюсь создать приложение для мобильных персонажей 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();
    }

}

В обработчике creationComplete CharactersView.mxml я создаю одноразовый символ с некоторой произвольной информацией, чтобы проверить, работает ли вставка символов. Каждый раз, когда я запускаю это, полностью как есть, оператор trace (длина моего массива) возвращает 1. Разве он не должен увеличиваться на единицу каждый раз, когда я запускаю его? Это говорит мне о том, что что-то не так, но не является ли администратор сохранением данных должным образом? Нужно ли мне проверять, возвращает ли pm.save() значение true, и если да, следует ли отправлять событие и только тогда запускать команду trace, чтобы получить правильную длину? Это кажется слишком сложным только для сохранения некоторых данных, поэтому я не совсем уверен, что происходит или как это исправить.

В любом случае, я спрашиваю, правильна ли моя текущая настройка, и если нет, есть ли у кого-нибудь простой пример, или мог бы создать простой пример, основанный на моем коде, для того, как правильно использовать 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 в List вызывает проблему?

1 ответ

Решение

Я не слишком знаком с этим, однако из документов видно, что вы, вероятно, не можете использовать универсальный объект, поскольку я не верю, что он реализует 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 будет сериализоваться автоматически, упорядочивая все свои элементы по порядку.

Другие вопросы по тегам