Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/220.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
android位图中奇怪的OutOfMemoryError:为什么显示并隐藏包含的视图可以避免它?_Android_Camera_Out Of Memory - Fatal编程技术网

android位图中奇怪的OutOfMemoryError:为什么显示并隐藏包含的视图可以避免它?

android位图中奇怪的OutOfMemoryError:为什么显示并隐藏包含的视图可以避免它?,android,camera,out-of-memory,Android,Camera,Out Of Memory,我是stackoverflow的常客,直到我遇到了一个我真的找不到任何存在的问题。这是我的第一个问题: 我正在构建一个摄像头应用程序,用户可以在进入下一步之前拍摄几张照片。我想让用户在相机阶段进行stying时可以查看和删除图片,因此我编写了一个自定义视图,用删除按钮显示已拍摄图像的缩略图。这些“拇指视图”包含在位于camerapreview SurfaceView顶部的线性布局中,默认可见性为“GONE”。用户可以通过按钮切换可见性 这一切都很好,但我有一个问题: 当我拍摄超过10张照片时,我

我是stackoverflow的常客,直到我遇到了一个我真的找不到任何存在的问题。这是我的第一个问题:

我正在构建一个摄像头应用程序,用户可以在进入下一步之前拍摄几张照片。我想让用户在相机阶段进行stying时可以查看和删除图片,因此我编写了一个自定义视图,用删除按钮显示已拍摄图像的缩略图。这些“拇指视图”包含在位于camerapreview SurfaceView顶部的线性布局中,默认可见性为“GONE”。用户可以通过按钮切换可见性

这一切都很好,但我有一个问题: 当我拍摄超过10张照片时,我会出现一个OutOfMemory错误。缩略图非常小,不会占用很多内存,而且我会回收原始位图,并在创建缩略图后执行System.gc()。 奇怪的是,当我按下按钮将包含线性布局的可见性设置为“可见”,然后再次设置为“消失”时,显然所有内存都被释放了,我可以拍摄比10张更多的照片。 我尝试过在代码中切换可见性,但这不起作用,还破坏了图形缓存。 除了按两次“我的可见性”按钮之外,还必须有另一种方法来释放内存;-)

以下是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);
}
}

答案很简单。当子视图(或容器)的可见性设置为“已消失”时,父布局(通常)将跳过它,甚至不需要渲染它。它不是“隐藏的”,它根本不存在


如果你的缩略图真的是缩略图,你不应该没有内存,但是,我认为你没有对它们进行下采样(我可能错了)。你怎么给他们看?你应该分享那段代码。(新照片->缩略图->图像视图)

我太傻了。显然,当视图保持消失时,将不会调用my onMeasure(),因此原始位图将保留在内存中。我将可见性更改为“不可见”,现在一切正常。

我正在使用onMeasure方法对它们进行下采样,在该方法中,我还在最后回收原始(大)位图。默认情况下,该视图已消失。如果我让它离开,它会碎的。如果我切换到VISIBLE,然后再切换回GONE,它就不会中断。下采样和垃圾收集肯定是按照你想要做的事情进行的——小到什么程度?我知道有一些人认为512X512是这样的,但是最终在RGB24中大约是768 K(512像素×512像素×3字节/像素)。768k*10个图像=7.6兆字节。这将推动Android heap limitsQuestion#2:您是手动将这些添加到视图中,还是使用类似listview的东西?它小于200*200,并且是一个手动嵌套的线性布局,在scrollview中,会产生两列网格。嘿,我打算提出这样的建议:)我将完全在视图之外处理位图逻辑…我在视图的onMeasure()方法中处理它,因为我需要拇指辫完全适合视图,在此之前我不知道视图的大小。我会投你一票,因为你让我再一次想起过去的能见度,但我还没有足够的声誉;-)