Blackberry: сохранение содержимого ListField и управление грязным состоянием

Я подготовил простой тестовый пример, чтобы продемонстрировать мою проблему.

Это всего лишь 1 файл, который будет запускаться мгновенно при добавлении в новый проект.

Я хотел бы, чтобы MainScreen отображал редактируемый список элементов:

скриншот

и при выходе из этого экрана пользователя следует спросить - хочет ли он сохранить измененный список в постоянное хранилище, представив стандартный диалог Сохранить / Отменить / Отменить:

скриншот

Я добавил setDirty (true) к своим пунктам меню, и стандартный диалог появляется нормально.

Моя проблема: я не знаю, как сбросить грязный флаг после сохранения - в моем текущем коде диалоговое окно «Сохранить / Отменить / Отменить» появляется снова и снова, даже если я просто просматриваю ListField, без редактирования.

src \ mypackage \ MyList.java:

package mypackage;

import java.util.*;
import net.rim.device.api.collection.*;
import net.rim.device.api.collection.util.*; 
import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.decor.*;
import net.rim.device.api.util.*;

public class MyList extends UiApplication implements FieldChangeListener {
    MyScreen myScreen = new MyScreen();

    public static void main(String args[]) {
        MyList app = new MyList();
        app.enterEventDispatcher();
    }

    public MyList() {
        MainScreen titleScreen = new MainScreen();
        titleScreen.setTitle("Click the button:");

        ButtonField myButton = new ButtonField("Show the list", ButtonField.CONSUME_CLICK) ;
        myButton.setChangeListener(this);
        titleScreen.add(myButton);

        pushScreen(titleScreen);
    }

    public void fieldChanged(Field field, int context) {
        pushScreen(myScreen);
    }
} 

class MyScreen extends MainScreen {
    ObjectListField myList = new ObjectListField();
    static PersistentObject myStore;
    static Vector myData;

    static {
        myStore = PersistentStore.getPersistentObject(0xb77f8e453754f37aL);
        myData = (Vector) myStore.getContents();
        if (myData == null) {
                myData = new Vector();
                myData.addElement("String 1");
                myData.addElement("String 2");
                myData.addElement("String 3");
                myStore.setContents(myData);
        }
    }

    public MyScreen() {
        setTitle("Edit the list below:");

        add(myList);

        addMenuItem(addItem);
        addMenuItem(editItem);
        addMenuItem(removeItem);
    }

    // load data from persistent store into the ListField
    private void loadData() {
        // clear the ListField
        myList.setSize(0);
        // copy data from the Vector to the ListField
        for (int i = myData.size() - 1; i >= 0; i--)
            myList.insert(0, myData.elementAt(i));
    }

    // save data from the ListField into the persistent store
    private void saveData() {
        // clear the Vector
        myData.removeAllElements();
        // copy data from the ListField to the Vector
        for (int i = myList.getSize() - 1; i >=0; i--)
            myData.addElement(myList.get(myList, i));

        synchronized(PersistentStore.getSynchObject()) {
            myStore.commit();
        }
    }

    protected void onUiEngineAttached(boolean attached) {
        if (attached) {
            loadData();
        }
    }

    public void save() {
        saveData();
        // UPDATE: when I call setDirty(false); here, then
        // the app starts displaying Save/Discard/Cancel dialog
        // on its exit - so there must be a better way...
    }

    private final MenuItem addItem = new MenuItem("Add Item", 0, 0) {  
        public void run() { 
            String[] buttons = {"Add", "Cancel"};
            Dialog myDialog = new Dialog("Add Item", buttons, null, 0, null);

            EditField myEdit = new EditField("Item: ", "");
            myDialog.add(myEdit);

            if (myDialog.doModal() == 0) {
                myList.insert(0, myEdit.getText());
                setDirty(true);
            }
        }
    };

    private final MenuItem editItem = new MenuItem("Edit Item", 0, 0) {  
        public void run() { 
            String[] buttons = {"Save", "Cancel"};
            Dialog myDialog = new Dialog("Edit Item", buttons, null, 0, null);

            int index = myList.getSelectedIndex();
            if (index == -1) {
                return;
            }

            String selectedItem = (String) myList.get(myList, index);
            EditField myEdit = new EditField("Item: ", selectedItem);
            myDialog.add(myEdit);

            if (myDialog.doModal() == 0) {
                myList.set(index, myEdit.getText());
                setDirty(true);
            }
        }
    };

    private final MenuItem removeItem = new MenuItem("Remove Item", 0, 0) {  
        public void run() { 
            String[] buttons = {"Delete", "Cancel"};
            Dialog myDialog = new Dialog("Remove Item", buttons, null, 0, null);

            int index = myList.getSelectedIndex();
            if (index == -1) {
                return;
            }

            String selectedItem = (String) myList.get(myList, index);
            LabelField myLabel = new LabelField("Really delete " + selectedItem + "?");
            myDialog.add(myLabel);

            if (myDialog.doModal() == 0) {
                myList.delete(index);
                setDirty(true);
            }
        }
    };
}

Поделитесь, пожалуйста, своим опытом работы с Blackberry 6, также приветствуются советы по поводу постоянного хранилища.

В моей реальной программе я использую KeywordFilterField для просмотра SortedReadableList, поэтому от читая документы Blackberry, я полагаю, что я всегда должен копировать данные между SortedReadableList и Vector - потому что последний является устойчивым, а первый - нет?


person Alexander Farber    schedule 27.04.2011    source источник
comment
Проблема в том, что ни один из вызовов сохранения не выполняется?   -  person jprofitt    schedule 28.04.2011
comment
Извините, я обновил свой вопрос, чтобы сделать его более понятным. Моя проблема в том, что (хотя код в основном работает нормально) диалог «Сохранить / Отменить / Отменить» появляется снова и снова - даже если я не редактирую список.   -  person Alexander Farber    schedule 28.04.2011
comment
Хммм .. Я это не воспроизводю. Добавление списка в конструктор экрана, а также загрузка его содержимого в onUiEngineAttached не делает экран грязным. Поэтому при выходе я не получаю диалоговое окно «Сохранить / Отменить / Отменить» (потому что экран остается незагрязненным). И поскольку я не получаю диалоговое окно, save() не вызывается, поэтому не имеет значения, изменяю ли я грязное состояние в save(). Итак, вопрос в том, что делает ваш экран грязным, если вы не редактируете список?   -  person Vit Khudenko    schedule 29.04.2011


Ответы (1)


setDirty (false) сбросит грязный флаг, если это то, что вам нужно.

person Richard    schedule 28.04.2011
comment
Спасибо, но когда я помещаю setDirty (false) в saveData (), приложение начинает отображать диалоговое окно «Сохранить / Отменить / Отменить» при выходе. - person Alexander Farber; 28.04.2011
comment
Вероятно, это связано с тем, что к моменту вызова данных сохранения программа уже прошла логику принятия решения о необходимости сохранения и запроса пользователя. Если вы хотите избежать появления этого всплывающего окна, вам нужно будет снять флажок, прежде чем пользователь покинет экран. - person Richard; 29.04.2011
comment
Спасибо, и я понял свою настоящую проблему: у меня есть KeywordFilterField в области заголовка MainScreen, и из-за этого его грязный бит игнорируется, когда Screen.onClose () смотрит, если какое-либо поле грязное. Я представил свою собственную переменную _dirty и написал собственный обработчик onClose (), чтобы обойти эту проблему. - person Alexander Farber; 02.05.2011