java.lang.runtimeexception:canvas:尝试使用回收的位图android.graphics.bitmap
-
12-12-2019 - |
题
我向这个处理程序发送消息(这里是我omomited某些情况)在位图上执行一些操作,然后在UI上设置位图。因为位图上的操作是耗时的,所以我把它放在一个线程中。当我完成这样做时,我将UI线程中的UI设置为 runonfithread 。
通常情况下,所有这些都运行良好,但在某些情况下,我收到以下例外: java.lang.runtimeexception:canvas:尝试使用回收的位图android.graphics.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;
}
}
};
方法旋转itdbitmap()和某些方法,它调用显示为bellow:
.
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();
}
解决方案
okey,让我回答我的问题。出现问题的原因是videoprocal.compress_success是由mhandler收到的两次。它在那里有多线程,所以在某些时候,发生“使用回收位图”问题。 至于为什么收到两次消息,呃......这是我的故障使用定时器任务。