在循环中创建位图时内存泄漏

时间:2011-09-14 10:56:14

标签: java android memory-leaks bitmap

我有一张地图应用。在我的代码中的某处,我将数据从数据库渲染到画布中。 我遇到了“内存不足”的异常,我无法弄清楚如何避免它。

这是相关方法。使用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);
}

我已经尝试过回收图片了,但是画布同意它无法使用回收的位图。

任何解决方案都会被贬低。

2 个答案:

答案 0 :(得分:2)

我建议使用位图缓存。即使在预蜂窝上回收图像也需要时间来释放内存(位图数据存储在不由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 :(得分:1)

  

我已经尝试过回收图片了,但是画布同意它无法使用回收的位图。

我认为这个想法是你应该“回收”位图,然后把它放在地板上让垃圾收集器来处理。

以下是javadoc对recycle()所说的内容:

  

“释放与此位图关联的本机对象,并清除对像素数据的引用。这不会同步释放像素数据;如果没有其他引用,它只是允许垃圾收集。位图已标记作为“死”,意味着如果调用getPixels()或setPixels(),它将抛出异常,并且不会绘制任何内容。此操作无法撤消,因此只有在确定没有进一步用途时才应调用它。 bitmap。这是一个高级调用,通常不需要调用,因为正常的GC进程会在没有更多对此位图的引用时释放这个内存。“。