首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在ArrayList上实现undo/redo的最佳方式

在ArrayList上实现undo/redo的最佳方式
EN

Stack Overflow用户
提问于 2013-02-07 11:18:16
回答 4查看 2K关注 0票数 0

对于这个问题的一般性,我很抱歉,但我不想从任何假设开始,以免错过大局

我有一个文档编辑类的应用程序(音乐符号),并想实现撤消和重做。所有相关的数据都保存在这个

代码语言:javascript
复制
static  ArrayList <TTEvt> mEvList;

在我的windows/MFC应用程序中,我只是序列化数据结构并将其放入堆栈。它使用了大量的内存,但是简单而又万无一失。

所以我想知道在android中保存和恢复我的ArrayList最好的方法是什么?

谢谢

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-02-07 18:09:51

所以这里是工作的多级撤销/重做代码。它工作得很好,但是太慢了。我去掉了gzip,这有点帮助,但它基本上使我的UI不可用。但至少它可以工作,我可以尝试从这里优化。

代码语言:javascript
复制
    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的速度。

票数 0
EN

Stack Overflow用户

发布于 2013-02-07 15:48:28

您可以使用Memento设计模式:这里有一个使用此模式http://www.youtube.com/watch?v=jOnxYT8Iaoo&list=PLF206E906175C7E07&index=25的undo/redo示例

票数 1
EN

Stack Overflow用户

发布于 2013-02-07 15:45:45

处理此问题的一种方法不是从数组中删除项,而是将它们标记为已删除并刷新视图,使其消失。因此,重做只会取消标记它们。在一些操作中,根据应用程序的逻辑,删除的项应该从数组中永久删除。

此外,还可以有一个单独的数组,其中撤消项,因为数组只保留对对象的引用,因此它不会占用太多内存,并且可以限制大小。

但是,如果undo/redo需要在设备关闭后仍然存在,则将每个项目的值保存到文件或数据库是唯一的选择。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14742936

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档