2011-09-14 5 views
3

지도 앱이 있습니다. 어딘가에 내 코드에서 데이터베이스의 데이터를 캔버스로 렌더링하고 있습니다. "메모리 부족"예외가 발생하여이를 피하는 방법을 알 수 없습니다.루프에서 비트 맵을 만들 때 메모리 누수가 발생했습니다.

다음은 관련 방법입니다. bitmapfactory로 비트 맵을 만들 때 예외가 발생합니다.

private static void _renderImage(Canvas g, Point[] points, RImageData imageData, 
           RMapView mapView) { 

    Bitmap image = (Bitmap)imageData.image; 
    Paint paint = new Paint(); 
    if(image == null) { 
     image = BitmapFactory.decodeByteArray(imageData.getImageBytes(), 0, 
               imageData.getImageBytes().length); 
     imageData.image = image; 
    } 
    g.drawBitmap(image, points[0].x, points[0].y, paint); 
} 

이미지를 리사이클 해보았지만 캔버스는 재활용 된 비트 맵으로 작동하지 않습니다.

어떤 해결책이라도 많이 들었을 것입니다.

+0

_renderImage()를 얼마나 자주 호출하고 있습니까? – mcfinnigan

+0

많이 있습니다. 캔버스에 그려지는 타일 (이미지 덩어리)을 상상해보십시오. – no9

답변

2

비트 맵 캐시가 필요합니다. 사전 허니 콤 (pre-honeycomb)에서 이미지를 재활용하는 경우에도 메모리를 확보하는 데 시간이 걸립니다 (비트 맵 데이터는 dalvik에서 직접 관리하지 않는 기본 메모리에 저장됩니다). 다음은 비트 맵 캐시의 샘플입니다. 필요에 맞게 조정하십시오.

/** 
* @author audrius Bitmap cache 
*/ 
private static class BitmapCache { 
    //private static final String TAG = "BitmapCache"; 
    private final int mCacheSize; 
    private final String mBitmapLocation; 
    private LinkedHashMap<String, Bitmap> mBitmapCache; 

    /** 
    * Constructor 
    * 
    * @param cacheSize 
    *   Cache size in element count (e.g. 8 = at most 8 Bitmaps in 
    *   cache) 
    * @param bitmapLocation 
    *   Physical root path to bitmap location 
    */ 
    public BitmapCache(int cacheSize, String bitmapLocation) { 
     mCacheSize = cacheSize; 
     mBitmapLocation = bitmapLocation; 

     mBitmapCache = new LinkedHashMap<String, Bitmap>(mCacheSize + 1) { 
      private static final long serialVersionUID = -4156123801558395154L; 

      @Override 
      protected boolean removeEldestEntry(
        java.util.Map.Entry<String, Bitmap> eldest) { 
       return size() > mCacheSize; 
      }; 

      @Override 
      public Bitmap remove(Object key) { 
       Bitmap bmp = super.get(key); 
       // make sure to release resources as soon as possible 
       bmp.recycle(); 
       return super.remove(key); 
      } 
     }; 
    } 

    /** 
    * Returns Bitmap (either from cache or physical location) 
    * 
    * @param bitmapFilename 
    * @return 
    */ 
    public Bitmap getBitmap(String bitmapFilename) { 
     Bitmap ret = mBitmapCache.get(bitmapFilename); 
     //Log.v(TAG, "getBitmap : " + bitmapFilename); 
     if (ret == null) { 
      //Log.v(TAG, "Bitmap not cached, reading location : " + mBitmapLocation); 
      ret = BitmapFactory.decodeFile(new File(mBitmapLocation, bitmapFilename).getAbsolutePath()); 
      mBitmapCache.put(bitmapFilename, ret); 
     } 

     return ret; 
    } 

    /** 
    * Clears bitmap cache 
    */ 
    public void clear() { 
     if (mBitmapCache != null) { 
      for (Bitmap bitmap : mBitmapCache.values()) { 
       if (bitmap != null) bitmap.recycle(); 
      } 

      mBitmapCache.clear(); 
     } 
    } 
} 
1

이미지를 리사이클 해보았지만 캔버스는 재활용 된 비트 맵으로 작동하지 않습니다.

나는 비트 맵을 "재사용"하고 가비지 컬렉터가 처리 할 플로어에 놓아야한다고 생각합니다. . 여기

은 javadoc에 대한 recycle() 말씀입니다 :

"이것은 기적 픽셀 데이터를 확보하지 않습니다이 비트 맵과 관련된 기본 객체를 해제하고, 픽셀 데이터에 대한 참조를 취소, 그것은 간단하게 할 수 있습니다 다른 참조가없는 경우 가비지 수집됩니다. 비트 맵은 "dead"로 표시되어 getPixels() 또는 setPixels()가 호출되면 예외를 발생시키고 아무것도 표시하지 않습니다.이 작업은 되돌릴 수 없으므로 비트 맵을 더 이상 사용하지 않을 경우에만 호출해야합니다.이 호출은 고급 호출이며 일반적으로 호출 할 필요가 없습니다. 일반적인 GC 프로세스는이 비트에 대한 참조가 더 이상 없을 때이 메모리를 비 웁니다 ap. "

+0

이 맞습니다. 하지만 제가 할 수있는 유일한 방법은이 방법에 있습니다. 그리고 "drawBitmap"호출 후에도 여전히 재활용하면 캔버스에서 오류가 발생합니다 ... – no9

관련 문제