1. 程式人生 > >Android手動回收bitmap,引發Canvas: trying to use a recycled bitmap處理

Android手動回收bitmap,引發Canvas: trying to use a recycled bitmap處理

contex highlight 比較 spa 代碼 soft use itl port

在做Android的開發的時候,在ListView 或是 GridView中需要加載大量的圖片,為了避免加載過多的圖片引起OutOfMemory錯誤,設置了一個圖片緩存列表 Map<String, SoftReference<Bitmap>> imageCache , 並對其進行維護,在圖片加載到一定數量的時候,就手動回收掉之前加載圖片的bitmap,此時就引起了如下錯誤:

Java代碼 技術分享圖片
  1. java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@41de4380
  2. at android.graphics.Canvas.throwIfRecycled(Canvas.java:1026)
  3. at android.graphics.Canvas.drawBitmap(Canvas.java:1127)
  4. at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:393)
  5. at android.widget.ImageView.onDraw(ImageView.java:961)
  6. at android.view.View.draw(View.java:13458)
  7. at android.view.View.draw(View.java:13342)
  8. at android.view.ViewGroup.drawChild(ViewGroup.java:2929)
  9. at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2799)
  10. at android.view.View.draw(View.java:13461)
  11. at android.view.View.draw(View.java:13342)

圖片手動回收部分代碼:

Java代碼 技術分享圖片
  1. Bitmap removeBitmap = softReference.get();
  2. if(removeBitmap != null && !removeBitmap.isRecycled()){
  3. removeBitmap.recycle(); //此句造成的以上異常
  4. removeBitmap = null;
  5. }

網上有好多人說應該把recycle()去掉,個人認為去掉後會引起內存持續增長,雖然將bitmap設置為了null,但是系統並沒有對其進行真正的回收,仍然占有內存,即是調用了System.gc() 強制回後以後,內存仍然沒有下去,如果依靠內存達到上限時系統自己回收的話,個人覺得太晚了,已經對應用造成了影響,應用應該是比較卡了,所以還是贊同加上bitmap.recycle() ,但是又會引起 Canvas: trying to use a recycled bitmap 異常,困擾了很久,開始嘗試從其它方面著手來解決這個問題,即然是異常就應該能夠捕獲到,但是在Adapter裏的getView()方法裏進行捕獲的時候,時機晚了,沒有捕獲到。現在換到在ImageView的onDraw()裏進行捕獲,上面的異常能夠捕獲。

解決方法(繼承ImageView 重寫onDraw()方法,捕獲異常):

在重寫onDraw()方法中,其實什麽都沒有做,只是添加了一個異常捕獲,即可捕捉到上面的錯誤

Java代碼 技術分享圖片
  1. import android.content.Context;
  2. import android.graphics.Canvas;
  3. import android.util.AttributeSet;
  4. import android.widget.ImageView;
  5. /**
  6. * 重寫ImageView,避免引用已回收的bitmap異常
  7. *
  8. * @author zwn
  9. *
  10. */
  11. public class MyImageView extends ImageView {
  12. public MyImageView (Context context, AttributeSet attrs) {
  13. super(context, attrs);
  14. }
  15. @Override
  16. protected void onDraw(Canvas canvas) {
  17. try {
  18. super.onDraw(canvas);
  19. } catch (Exception e) {
  20. System.out
  21. .println("MyImageView -> onDraw() Canvas: trying to use a recycled bitmap");
  22. }
  23. }
  24. }

Android手動回收bitmap,引發Canvas: trying to use a recycled bitmap處理