2012-07-26 62 views
0

我發送消息給這個處理程序(這裏我省略了一些情況)在位圖上執行一些操作,然後在UI上設置位圖。因爲位圖上的操作很耗時,所以我把它放在一個線程中。當我完成這個工作時,我使用方法runOnUiThread在UI線程中設置UI。
通常情況下,這一切都運行良好,但在某些情況下,我得到了以下異常:了java.lang.RuntimeException:畫布:試圖使用回收的位圖android.graphics.Bitmap
這種情況非常罕見,但確實發生過幾次。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; 
} 

從代碼,這個問題必須在此聲明ocuured:

Drawable drawable = new BitmapDrawable(bitmap); 

但根據在代碼上下文中,位圖不應該是空的或者可以被回收的,這真是奇怪。

我一直在這個問題上徘徊近兩天,無法弄清楚問題是什麼,但問題確實存在。有人能給我一些建議嗎?任何迴應表示讚賞!謝謝!

順便說一下,當我嘗試這樣的RuntimeException時,這種異常無法捕捉,爲什麼?

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

回答

0

Okey,讓我回答我的問題。發生此問題的原因是mHandler接收到VideoProtocal.COMPRESS_SUCCESS兩次。它有多線程,所以在某些時候會出現「使用回收位圖」問題。 至於爲什麼兩次收到消息,呃...這是我的錯誤使用計時器任務。