java.lang.RuntimeException:Canvas:尝试使用循环位图android.graphics.Bitmap

时间:2012-07-26 14:59:41

标签: android bitmap garbage-collection recycle

我向此处理程序发送消息(这里我省略了一些情况)对位图执行某些操作,然后在UI上设置位图。因为位图上的操作很耗时,所以我把它放在一个线程中。完成此操作后,我使用方法 runOnUiThread 在UI线程中设置UI。
通常,所有这些都运行良好,但在某些情况下我得到以下异常: java.lang.RuntimeException:Canvas:尝试使用回收的位图android.graphics.Bitmap
它发生得非常罕见,但确实发生了好几次。

private Handler mHandler = new Handler()
{
    @Override
    public void handleMessage(Message msg)
    {
        int what = msg.what;
        switch (what)
        {

            case VideoProtocal.COMPRESS_SUCCESS:
                state = State.COMPRESSED;
                recordBack.setVisibility(View.VISIBLE);
                recordSend.setVisibility(View.VISIBLE);
                playButton.setVisibility(View.VISIBLE);
                new Thread(){
                    @Override
                    public void run()
                    {
                        rotationBitmap();
                        runOnUiThread(new Runnable() {
                            public void run() {
                                if( null != bitmap && !bitmap.isRecycled() )
                                {
                                    Drawable drawable = new BitmapDrawable(bitmap);
                                    fristFrame.setBackgroundDrawable(drawable);
                                }
                            }
                        });
                    }
                }.start();
                mFrameCount = 0;
                getVideoSize();
                videoTime = getVideoFileTime(mp4_path) / 1000;
                timeView.setText(getString(R.string.video_count, videoTime));
                deleteTempFile();
                LogX.trace(TAG, "COMPRESS_SUCCESS");
                dismissProgress();
                break;
            default:
                break;
        }
    }

};

方法rotationBitmap()及其调用的方法如下所示:

private void rotationBitmap()
{
    int width = (int) (PIC_WIDTH * FusionField.currentDensity);
    int height = (int) (PIC_HIGHT * FusionField.currentDensity);
    Bitmap bmTemp = bitmap;
    bitmap = CommonUtil.resizeImage(bitmap, width, height);

    if (bmTemp != null && !bmTemp.isRecycled() && bmTemp != bitmap)
    {
        bmTemp.recycle();
        bmTemp = null;
    }

    rotate(bitmap, rotationAngle());

    CommonUtil.checkMysoftStage(FusionCode.videoThumbnail);
    String videoName = CommonUtil.getUniqueName(".jpg", FusionCode.videoName);
    jpg_path = FusionCode.videoThumbnail + "/" + videoName;
    try
    {
        FileOutputStream fos = new FileOutputStream(jpg_path);
        if (bitmap != null)
        {
            bitmap.compress(CompressFormat.JPEG, 50, fos);
        }
        fos.close();
    }
    catch (FileNotFoundException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    catch (IOException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}


private Bitmap rotate(Bitmap b, int degrees)
{
    if (degrees != 0 && b != null)
    {
        Matrix m = new Matrix();
        m.setRotate(degrees, (float) b.getWidth() / 2, (float) b.getHeight() / 2);
        try
        {
            bitmap = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), m, true);
        }
        catch (OutOfMemoryError ex)
        {
            // TODO Auto-generated catch block
            ex.printStackTrace();
        }
    }
    return b;
}

从代码中,问题必须在此声明中出现:

Drawable drawable = new BitmapDrawable(bitmap);

但根据代码上下文,位图不应为null或回收,这很奇怪。

我差不多两天一直在讨论这个问题,无法弄清楚问题是什么,但问题确实存在。有人可以给我一些建议吗?任何回应表示赞赏!谢谢!

顺便说一句,当我尝试像这样的RuntimeException时,无法捕获这种异常,为什么?

try
{
    bitmap.recycle();
    Drawable drawable = new BitmapDrawable(bitmap);
    fristFrame.setBackgroundDrawable(drawable);
}
catch (RuntimeException e)
{
    e.printStackTrace();
}

1 个答案:

答案 0 :(得分:0)

哎呀,让我回答一下我的问题。出现此问题的原因是mHandler两次收到VideoProtocal.COMPRESS_SUCCESS。它有多线程,所以在某些时候,会出现“使用循环位图”问题。 至于为什么收到两次消息,呃...这是我使用计时器任务的错误。