sorry about the general nature of this question but i don't want to start with any assumptions for fear of missing the big picture
i have a document editing kind of app (music notation) and want to implement undo and redo. all the relevant data is held in this
static ArrayList <TTEvt> mEvList;
in my windows/MFC app, i just serialize the data structure and put it on a stack. it uses lots of memory but easy and foolproof.
so i was wondering what's the bast way to save and restore my ArrayList in android?
thanks
so here is the working multilevel undo/redo code. it works fine but it is sloooow. i took the gzip out which helps a bit but it basically makes my UI unusable. but at least it works, i can try optimize from here.
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();
}
}
note that your should call addUndoCheckpoint BEFORE you change ArrayList. i'm currently working on a version that you can call after you change ArrayList. this has the advantage that you can do addUndoCheckpoint in the background and not slow down the UI.