2

私がやっているのはアプリケーションの描画であり、このプロジェクトに必要な2つの機能は元に戻すとやり直しです..そのため、ユーザーが描画して画面から指を離すたびに、以前の描画のリストを保存する必要があります..

これは前の図面を保存するときのコードです

    public void saveState() {

    State mUndoState = new State();
    saveState(mSurface.getBitmap(), mUndoState);
}

private void saveState(Bitmap bitmap, State state) {
    state.mBuffer = new byte[bitmap.getRowBytes() * bitmap.getHeight()];
    Buffer byteBuffer = ByteBuffer.wrap(state.mBuffer);
    bitmap.copyPixelsToBuffer(byteBuffer);
    mListUndoState.add(state);
    System.out.println("Size now: " + (mListUndoState.size() - 1));
    mListRedoState.clear();
    mListRedoState.add(state);
    // StylesFactory.saveState(state.stylesState);
}
    private static class State {
    byte[] mBuffer = null;
    // final HashMap<Integer, Object> stylesState = new HashMap<Integer,
    // Object>();
}

問題は、Android デバイスのヒープ メモリが 16 MB しかないことです。この問題に対処する最善の方法は何ですか? .. ListUndoState に 7 ~ 10 回しか保存できず、メモリ不足の例外が発生しました.. 元に戻すアクションを無制限に取得するか、少なくとも 50 回以上実行したいと考えています。

元に戻すとやり直すために前の描画を保存する完全なクラスを次に示します。

package com.appshouse.drawgram.utli;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import android.graphics.Bitmap;

public class HistoryHelper {
    private final Surface mSurface;
    private List<State> mListUndoState = new ArrayList<State>();
    private List<State> mListRedoState = new ArrayList<State>();


public HistoryHelper(Surface surface) {
    mSurface = surface;

}

public void undo() {
    int length = mListUndoState.size() - 1;

    if (length <= 0) {
        System.out.println("no element is list");
        return;
    }
    System.out.println("history undo size: " + length);
    restoreState(mSurface.getBitmap(), mListUndoState.get(length - 1));

    mListRedoState.add(mListUndoState.get(length));
    mListUndoState.remove(length);
}

public void redo() {
    int length = mListRedoState.size() - 1;

    if (length <= 0) {
        System.out.println("no element is list");
        return;
    }
    System.out.println("history undo size: " + length);
    restoreState(mSurface.getBitmap(), mListRedoState.get(length));
    mListUndoState.add(mListRedoState.get(length));
    mListRedoState.remove(length);

}

private void restoreState(Bitmap bitmap, State state) {
    Buffer byteBuffer = ByteBuffer.wrap(state.mBuffer);
    bitmap.copyPixelsFromBuffer(byteBuffer);
    // StylesFactory.restoreState(state.stylesState);
}

public void saveState() {
    State mUndoState = new State();
    saveState(mSurface.getBitmap(), mUndoState);
}

private void saveState(Bitmap bitmap, State state) {
    state.mBuffer = new byte[bitmap.getRowBytes() * bitmap.getHeight()];
    Buffer byteBuffer = ByteBuffer.wrap(state.mBuffer);
    bitmap.copyPixelsToBuffer(byteBuffer);
    mListUndoState.add(state);
    System.out.println("Size now: " + (mListUndoState.size() - 1));
    mListRedoState.clear();
    mListRedoState.add(state);
    // StylesFactory.saveState(state.stylesState);
}

private static class State {
    byte[] mBuffer = null;
    // final HashMap<Integer, Object> stylesState = new HashMap<Integer,
    // Object>();
}

}
4

1 に答える 1

0

hieuxit が提案するように、ビットマップをファイル キャッシュに保存してこの問題を解決しますが、これが最善の解決策かどうかはわかりません。

ここに私が前のクラスで変更したものがあります

package com.appshouse.drawgram.utli;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.widget.Toast;

public class HistoryHelper {
    private final Surface mSurface;
    int undoAvailable = 0;
    int redoAvailable = 0;
    Context context;

    public HistoryHelper(Context c, Surface surface) {
        mSurface = surface;
        context = c;
    }

    public void undo() {

        if (undoAvailable > 1) {
            undoAvailable--;
            new LoadRestoreState().execute();
            redoAvailable ++;
        } else {
            Toast.makeText(context, "End of Undo Data", Toast.LENGTH_LONG)
                    .show();
        }
    }
public void redo() {
    if(redoAvailable >= 1)
    {
        undoAvailable ++;
        new LoadRestoreState().execute();
        redoAvailable --;
    }else
    {
        Toast.makeText(context, "End of Redo Data", Toast.LENGTH_LONG)
        .show();
    }
}


public void saveState() {
    new LoadSaveState().execute(mSurface.getBitmap());
}


private class LoadSaveState extends AsyncTask<Bitmap, Void, Void>
{
    @Override
    protected Void doInBackground(Bitmap... params) {
        undoAvailable++;
        FileCache fileCache = new FileCache(context, String.valueOf(undoAvailable));
        String str_buffer = Common.getStringDrawing(params[0]);
        fileCache.writeFile(str_buffer);
        redoAvailable = 0;
        return null;
    }
}

private class LoadRestoreState extends AsyncTask<Void , Void, Void>
{

    @Override
    protected Void doInBackground(Void... params) {
        FileCache getFileChach = new FileCache(context,
                String.valueOf(undoAvailable));
        String image_str = getFileChach.readFile();
        Bitmap drawing = Common.getBitmapFromString(image_str);
        byte[] buffer = new byte[drawing.getRowBytes()
                * drawing.getHeight()];
        Buffer byteBuffer = ByteBuffer.wrap(buffer);
        drawing.copyPixelsToBuffer(byteBuffer);
        byteBuffer = ByteBuffer.wrap(buffer);
        mSurface.getBitmap().copyPixelsFromBuffer(byteBuffer);
        return null;
    }
}
}

FileCache クラスの場所:

    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;

    import android.content.Context;

    public class FileCache {

        private File cacheDir;
        private File TempFile;

        public FileCache(Context context, String Filename) {

            cacheDir = context.getCacheDir();
            if (!cacheDir.exists())
                cacheDir.mkdirs();
            TempFile = new File(cacheDir.getPath(), Filename);
        }

        public void writeFile(String buffer)

 {
        FileWriter writer = null;
        try {
            writer = new FileWriter(TempFile);
            writer.write(buffer);
            System.out.println(TempFile + " File - data: " + buffer.toString()
                    );
            writer.close();
        } catch (IOException e) {

        }
    }

    public String readFile() {
        String strLine = "";
        StringBuilder text = new StringBuilder();
        try {
            FileReader fileReader = new FileReader(TempFile);
            BufferedReader bufferReader = new BufferedReader(fileReader);
            while ((strLine = bufferReader.readLine()) != null) {
                text.append(strLine + "\n");
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("get text String: "+text.toString());
        return text.toString();
    }

    public void clear() {
        File[] files = cacheDir.listFiles();
        if (files == null)
            return;
        for (File f : files)
            f.delete();
    }

}

そして、Common クラスで作成した 2 つの関数を次に示します。

public static String getStringDrawing(Bitmap bm) {
    String image_str = "";
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    byte[] byte_arr;
    bm.compress(Bitmap.CompressFormat.PNG, 90, stream);
    byte_arr = stream.toByteArray();
    image_str = Base64.encodeBytes(byte_arr);
    return image_str;
}

public static Bitmap getBitmapFromString(String img_str)
{
    Bitmap bmImg = null;
    try {
        byte[] encodeByte = null;
        encodeByte = Base64.decode(img_str);
        bmImg = BitmapFactory.decodeByteArray(encodeByte, 0,
                encodeByte.length);
        bmImg = Bitmap.createBitmap(bmImg);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return bmImg;
}

もちろん、画像を文字列に、またはその逆に変換するには、base64 クラスをダウンロードする必要があります。

于 2013-08-23T19:13:17.517 に答える