对于这个问题的一般性,我很抱歉,但我不想从任何假设开始,以免错过大局
我有一个文档编辑类的应用程序(音乐符号),并想实现撤消和重做。所有相关的数据都保存在这个
static ArrayList <TTEvt> mEvList;在我的windows/MFC应用程序中,我只是序列化数据结构并将其放入堆栈。它使用了大量的内存,但是简单而又万无一失。
所以我想知道在android中保存和恢复我的ArrayList最好的方法是什么?
谢谢
发布于 2013-02-07 18:09:51
所以这里是工作的多级撤销/重做代码。它工作得很好,但是太慢了。我去掉了gzip,这有点帮助,但它基本上使我的UI不可用。但至少它可以工作,我可以尝试从这里优化。
static LinkedList<byte[]> undoStack = new LinkedList<byte[]>();
static LinkedList<byte[]> redoStack = new LinkedList<byte[]>();
public static void addUndoCheckpoint() {
long start = System.currentTimeMillis();
byte[] byteBuf = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// GZIPOutputStream gzipOut = new GZIPOutputStream(baos);
ObjectOutputStream objectOut = new ObjectOutputStream(baos);
for (TTEvt ev : Doc.mEvList)
objectOut.writeObject(ev);
objectOut.close();
byteBuf = baos.toByteArray();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
undoStack.push(byteBuf);
if (undoStack.size() > 10)
undoStack.removeLast(); // limit size
redoStack.clear();
long end = System.currentTimeMillis();
Log.d("MainView", "addUndoCheckpoint time=" + (end - start) + "mS");
}
public static void doUndo() {
if (undoStack.size() == 0)
return;
// push current state onto redo stack first
byte[] byteBuf = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// GZIPOutputStream gzipOut = new GZIPOutputStream(baos);
ObjectOutputStream objectOut = new ObjectOutputStream(baos);
for (TTEvt ev : Doc.mEvList)
objectOut.writeObject(ev);
objectOut.close();
byteBuf = baos.toByteArray();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
redoStack.push(byteBuf); // push current state onto redo stack
if (redoStack.size() > 10)
redoStack.removeLast();
// now undo
mEvList.clear();
byteBuf = undoStack.pop();
ObjectInputStream objectIn = null;
try {
ByteArrayInputStream bais = new ByteArrayInputStream(byteBuf);
// GZIPInputStream gzipIn;
// gzipIn = new GZIPInputStream(bais);
objectIn = new ObjectInputStream(bais);
while (true) {
TTEvt ev = (TTEvt) objectIn.readObject();
if (ev == null)
break;
Doc.mEvList.add(ev);
}
objectIn.close();
} catch (IOException e) {
// this is the normal exit
if (objectIn != null) {
try {
objectIn.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
// e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MainView.forceTotalRedraw();
}
public static void doRedo() {
if (redoStack.size() == 0)
return;
// push current state onto undo stack first so we can undo the redo
byte[] byteBuf = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// GZIPOutputStream gzipOut = new GZIPOutputStream(baos);
ObjectOutputStream objectOut = new ObjectOutputStream(baos);
for (TTEvt ev : Doc.mEvList)
objectOut.writeObject(ev);
objectOut.close();
byteBuf = baos.toByteArray();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
undoStack.push(byteBuf); // push current state onto redo stack
if (undoStack.size() > 10)
undoStack.removeLast();
// now redo
mEvList.clear();
byteBuf = redoStack.pop();
ObjectInputStream objectIn = null;
try {
ByteArrayInputStream bais = new ByteArrayInputStream(byteBuf);
// GZIPInputStream gzipIn;
// gzipIn = new GZIPInputStream(bais);
objectIn = new ObjectInputStream(bais);
while (true) {
TTEvt ev = (TTEvt) objectIn.readObject();
if (ev == null)
break;
Doc.mEvList.add(ev);
}
objectIn.close();
} catch (IOException e) {
// this is the normal exit
if (objectIn != null) {
try {
objectIn.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
// e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MainView.forceTotalRedraw();
}
}请注意,您应该在更改ArrayList之前调用addUndoCheckpoint。我目前正在开发一个版本,您可以在更改ArrayList后调用它。这样做的好处是,您可以在后台执行addUndoCheckpoint,而不会减慢UI的速度。
发布于 2013-02-07 15:48:28
您可以使用Memento设计模式:这里有一个使用此模式http://www.youtube.com/watch?v=jOnxYT8Iaoo&list=PLF206E906175C7E07&index=25的undo/redo示例
发布于 2013-02-07 15:45:45
处理此问题的一种方法不是从数组中删除项,而是将它们标记为已删除并刷新视图,使其消失。因此,重做只会取消标记它们。在一些操作中,根据应用程序的逻辑,删除的项应该从数组中永久删除。
此外,还可以有一个单独的数组,其中撤消项,因为数组只保留对对象的引用,因此它不会占用太多内存,并且可以限制大小。
但是,如果undo/redo需要在设备关闭后仍然存在,则将每个项目的值保存到文件或数据库是唯一的选择。
https://stackoverflow.com/questions/14742936
复制相似问题