2

私は、実際には何も存在しないという問題に遭遇するまで、stackoverflowに頻繁にゲストとして参加していました。だからここに私の最初の質問があります:

次のステップに進む前に、ユーザーが複数の写真を撮ることができるカメラアプリを構築しています。カメラステージでスタイリングしながら写真を確認および削除できるようにしたいので、削除ボタンを使用して、すでにキャプチャされた画像のサムネイルを表示するカスタムビューを作成しました。これらの「Thumbviews」は、camerapreview-SurfaceViewの上部にあるLinearLayoutに含まれており、デフォルトの可視性は「GONE」です。ユーザーはボタンで表示を切り替えることができます。

すべて正常に動作しますが、問題が1つあります。約10枚以上の写真を撮ると、OutOfMemoryErrorが発生します。サムネイルは非常に小さく、メモリをあまり消費しません。また、元のビットマップをリサイクルし、サムネイルを作成した後にSystem.gc()を実行します。奇妙なことに、含まれているLinearLayoutの可視性を「VISIBLE」に設定し、再び「GONE」に設定するボタンを押すと、明らかにすべてのメモリが解放され、10枚よりも多くの写真を撮ることができます。切り替えてみましたコードでの可視性は機能しませんが、描画キャッシュも破壊されます。可視性ボタンを2回押す以外に、そのメモリを解放する別の方法が必要です;-)

ThumbViewのコードは次のとおりです。

public class ThumbView extends View {

private Bitmap mBitmap;
private Bitmap mScaledBitmap;
private int mWidth, mHeight, mPosX, mPosY;
static private Bitmap mDeleteBitmap;
private File mPreviewFile;
private File mFinalFile;
private Orientation mOrientation;
private boolean mRed;

public ThumbView(Context context, Bitmap bitmap, File previewFile, File finalFile, Orientation orientation) {
    super(context);
    mBitmap = bitmap;
    mPreviewFile = previewFile;
    mFinalFile = finalFile;
    mOrientation = orientation;
    if(mDeleteBitmap != null)
        return;
    mDeleteBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.deletebutton);
}

public void deleteFile()
{
    if(mPreviewFile != null && mPreviewFile.exists())
    {
        mPreviewFile.delete();
    }
    if(mFinalFile != null && mFinalFile.exists())
    {
        mFinalFile.delete();
    }
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    mWidth  = MeasureSpec.getSize(widthMeasureSpec);
    setMeasuredDimension(mWidth, mWidth);

    if(mBitmap == null)
        return;
    mHeight = mWidth;

    float bitmapRatio = mBitmap.getWidth() / (float) mBitmap.getHeight();

    if(bitmapRatio > 1)
    {
        mScaledBitmap = Bitmap.createScaledBitmap(mBitmap, mWidth,
                (int)(mWidth/bitmapRatio), true);
        mPosY = (mWidth-mScaledBitmap.getHeight())/2;
    }
    else
    {
        mScaledBitmap = Bitmap.createScaledBitmap(mBitmap, (int)(mHeight*bitmapRatio),
                mHeight, true);
        mPosX = (mHeight-mScaledBitmap.getWidth())/2;
    }


    Matrix mtx = new Matrix();
    mtx.postRotate(-90);

    Bitmap b = Bitmap.createBitmap(mScaledBitmap, 0, 0, mScaledBitmap.getWidth(), mScaledBitmap.getHeight(), mtx, true);
    mScaledBitmap = b;
    b = null;

    mBitmap.recycle();
    mBitmap = null;
    System.gc();
}

public boolean deleteButtonPressed(float x, float y)
{
    Rect r = new Rect(mPosY, mPosX, mPosY+mDeleteBitmap.getWidth(),
            mPosX+mDeleteBitmap.getHeight());
    if(r.contains((int)x, (int)y))
    {
        return true;
    }
    return false;
}

public void setRed(boolean red)
{
    mRed = red;
    invalidate();
}

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(mScaledBitmap, mPosY, mPosX, new Paint());
    canvas.drawBitmap(mDeleteBitmap, mPosY, mPosX, new Paint());
    if(mRed)
        canvas.drawColor(0x55FF0000);
}

}

4

2 に答える 2

2

「なぜ壊れないのか」の答えは簡単です。子ビュー (またはコンテナー) の可視性が GONE に設定されている場合、親レイアウトは (通常) それをスキップし、わざわざレンダリングすることさえしません。それは「隠されている」のではなく、まったく存在しません。

サムネイルが実際にサムネイルである場合、メモリが不足することはありませんが、ダウンサンプリングしていないと思います (間違っている可能性があります)。それらをどのように示していますか?そのコードを共有する必要があります。(新規写真 -> サムネイル画像 -> 画像表示)

于 2012-10-25T17:24:04.703 に答える
0

私はとても愚かです。明らかに、View が GONE のままである間は onMeasure() は呼び出されないため、元のビットマップはメモリに残ります。可視性を INVISIBLE に変更したところ、すべて正常に動作するようになりました。

于 2012-10-25T20:29:32.793 に答える