0

この質問の一般的な性質については申し訳ありませんが、全体像を見落とす恐れがあるため、仮定から始めたくありません。

ドキュメント編集の種類のアプリ(楽譜)があり、元にたりやり直しを実装したいと思っています。すべての関連データはこれに保持されます

static  ArrayList <TTEvt> mEvList;

私のwindows/MFCアプリでは、データ構造をシリアル化してスタックに配置するだけです。大量のメモリを使用しますが、簡単で確実です。

だから私はAndroidで私のArrayListを保存して復元するための最も簡単な方法は何ですか?

ありがとう

4

4 に答える 4

1

Mementoデザインパターンを使用できます。ここに、このパターンを使用した元に戻す/やり直しの例がありますhttp://www.youtube.com/watch?v=jOnxYT8Iaoo&list=PLF206E906175C7E07&index=25

于 2013-02-07T07:48:27.570 に答える
0

参考までに、私はいくつかのオプションを考え出しました。

最も簡単な方法は、次のようにtoArrayを使用してArrayListをオブジェクトの単純な配列に書き込むことです。

static TTEvt evArray[];

    public static void addUndoCheckpoint() {

        long start  = System.currentTimeMillis();

        evArray = Doc.mEvList.toArray(new TTEvt[Doc.mEvList.size()]);

        long end = System.currentTimeMillis();
        Log.d("MainView", "addUndoCheckpoint time="+(end-start)+"mS");
    }
    public static void doUndo() {

        Doc.mEvList.clear();
        for(TTEvt ev : evArray)
            Doc.mEvList.add(ev);

        forceTotalRedraw();
    }

更新:toArrayは、オブジェクト自体ではなく、オブジェクトへの参照の配列に対してのみ新しいものを実行するため、上記のコードが実際には機能していないことがわかりました。したがって、すべてのオブジェクトのクローンを作成する必要があります。これは明らかに大量のメモリであり、おそらく時間です。おそらく答えは以下の遅いオプションで、シリアル化を使用しますが、UIが遅くならないように、同期スレッドで実行します。

このようなスペースを節約するためにgzip圧縮を使用するより複雑な方法

  static byte[] undoBuf;

  public static void addUndoCheckpoint() {

    long start  = System.currentTimeMillis();

    //evArray = Doc.mEvList.toArray(new TTEvt[Doc.mEvList.size()]);

    try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        GZIPOutputStream gzipOut = new GZIPOutputStream(baos);
        ObjectOutputStream objectOut = new ObjectOutputStream(gzipOut);
        for(TTEvt ev: Doc.mEvList)
            objectOut.writeObject(ev);
        objectOut.close();
        undoBuf = baos.toByteArray();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    long end = System.currentTimeMillis();
    Log.d("MainView", "addUndoCheckpoint time="+(end-start)+"mS");
  }

  public static void doUndo() {

    Doc.mEvList.clear();
    //for(TTEvt ev : evArray)
    //  Doc.mEvList.add(ev);

    try {
        ByteArrayInputStream bais = new ByteArrayInputStream(undoBuf);
        GZIPInputStream gzipIn;
        gzipIn = new GZIPInputStream(bais);
        ObjectInputStream objectIn = new ObjectInputStream(gzipIn);
        while(objectIn.available()>0) {
            TTEvt ev = (TTEvt) objectIn.readObject();
            Doc.mEvList.add(ev);
        }
        objectIn.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }


    forceTotalRedraw();
}

これに伴う問題は、その速度が遅く、約5000エントリのデータ構造体の場合はほぼ1秒です。

これは現時点では1レベルの取り消しであり、現在、複数のレベルを維持するためにスタックを実装しており、メモリ圧縮でより高速なものを探しています

于 2013-02-07T07:53:19.973 に答える
0

だからここに動作するマルチレベルの元に/やり直しコードがあります。それはうまく動作しますが、それは遅いです。私は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-07T10:09:51.290 に答える
0

これに対処する1つの方法は、配列からアイテムを削除するのではなく、アイテムに削除済みのフラグを付け、ビューを更新してアイテムが消えるようにすることです。したがって、Redoはそれらのフラグを解除します。一部の操作では、アプリのロジックに応じて、削除されたアイテムを配列から完全に削除する必要があります。

また、元に戻すアイテムがある別の配列を持つこともできます。配列はオブジェクトへの参照のみを保持するため、メモリをあまり消費せず、サイズを制限できます。

ただし、元に戻す/やり直しがデバイスのシャットダウン後も存続する必要がある場合は、各アイテムの値をファイルまたはデータベースに保存することが唯一のオプションです。

于 2013-02-07T07:45:45.347 に答える