2011-04-27 77 views
0

我准备了一个简单的测试用例来演示我的问题。黑莓:保存ListField内容和脏状态管理

这只是一个文件,它会在添加到新项目时立即运行。

我想有一个MainScreen显示项目的可编辑列表:

screenshot

,在离开该屏幕时,用户应该问 - 如果她要保存修改列表永久存储,通过提供标准的保存/放弃/取消-对话框:

screenshot

我已经加入使用setDirty(真)我的菜单项,并拿出奥卡标准对话框不年。

我的问题是:我不知道如何清除脏标志保存后 - 在我当前的代码保存/放弃/取消-对话框一次又一次来了,即使我刚刚查看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); 
      } 
     } 
    }; 
} 

请分享你的黑莓6的经验,关于持久性存储建议,也欢迎。

在我的真实程序中,我使用的是KeywordFilterField for viewing a SortedReadableList,所以从阅读Blackberry文档我想,我必须总是在SortedReadableList和Vector之间复制数据 - 因为后者是可持久的,而前者不是?

+0

是否存在任何保存调用都未命中的问题? – jprofitt 2011-04-27 20:31:19

+0

对不起,我已更新我的问题以使其更清楚。我的问题是(尽管代码大部分工作正常),保存/放弃/取消对话会一次又一次 - 即使我不编辑列表。 – 2011-04-28 09:40:02

+0

嗯..我不重现这一点。在屏幕构造函数中添加一个列表以及在'onUiEngineAttached'中加载它的内容不会使屏幕变脏。所以在退出时,我没有得到保存/放弃/取消对话框(因为屏幕保持非脏)。由于我没有得到对话框,因此不调用'save()',所以在save()中更改脏状态并不重要。所以问题是“当你不编辑列表时,你的屏幕变脏了吗?” – 2011-04-28 23:14:10

回答

0

setDirty(false)将清除脏标志,如果这是你以后的事情。

+0

谢谢,但是当我把setDirty(false)放入saveData()时,应用程序在退出时开始显示保存/放弃/取消对话框。 – 2011-04-28 11:35:32

+0

这可能是因为在调用保存数据时,程序已经经历了决定保存的逻辑并可能需要提示用户。如果你想避开那个弹出窗口,你必须在用户退出屏幕之前清除标志。 – Richard 2011-04-29 11:15:23

+0

谢谢,我已经想出了我的真正问题:我在MainScreen标题区域有KeywordFilterField,并且因为它的脏位在Screen.onClose()看起来如果任何Field是脏的时被忽略。我已经介绍了自己的_dirty变量并编写了自己的onClose()处理程序来解决这个问题。 – 2011-05-02 13:36:27