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

Java 在循环中创建位图时内存泄漏,java,android,memory-leaks,bitmap,Java,Android,Memory Leaks,Bitmap,我有一个地图应用程序。在代码的某个地方,我正在将数据从数据库渲染到画布中。 我遇到了“内存不足”异常,我不知道如何避免它 以下是相关的方法。使用bitmapfactory创建位图时出现异常 private static void _renderImage(Canvas g, Point[] points, RImageData imageData, RMapView mapView) { Bitmap image =

我有一个地图应用程序。在代码的某个地方,我正在将数据从数据库渲染到画布中。 我遇到了“内存不足”异常,我不知道如何避免它

以下是相关的方法。使用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);
}
我曾尝试过回收图像,但画布上却声称它无法与回收的位图一起使用

任何解决方案都将受到高度重视

我曾尝试过回收图像,但画布上却声称它无法与回收的位图一起使用

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

以下是javadoc关于
recycle()
的内容:

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


我建议使用位图缓存。即使在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();
        }
    }
}
/**
*@author audrius位图缓存
*/
私有静态类BitmapCache{
//私有静态最终字符串标记=“BitmapCache”;
私人最终整数大小;
私有最终字符串mBitmapLocation;
私有LinkedHashMap MbitMacache;
/**
*建造师
* 
*@param cacheSize
*缓存大小(以元素计数为单位)(例如,8=中最多8个位图)
*缓存)
*@param位图位置
*位图位置的物理根路径
*/
公共位图缓存(int cacheSize、字符串位图位置){
mCacheSize=缓存大小;
mBitmapLocation=位图位置;
mbitMacache=新的LinkedHashMap(mCacheSize+1){
私有静态最终长serialVersionUID=-4156123801558395154L;
@凌驾
保护布尔重构(
java.util.Map.Entry(最早){
返回大小()>mCacheSize;
};
@凌驾
公共位图删除(对象键){
位图bmp=super.get(键);
//确保尽快释放资源
bmp.recycle();
返回super.remove(键);
}
};
}
/**
*返回位图(从缓存或物理位置)
* 
*@param bitmapFilename
*@返回
*/
公共位图getBitmap(字符串bitmapFilename){
位图ret=mBitmapCache.get(位图文件名);
//Log.v(标记“getBitmap:+bitmapFilename”);
if(ret==null){
//Log.v(标记,“位图未缓存,读取位置:”+mBitmapLocation);
ret=BitmapFactory.decodeFile(新文件(mBitmapLocation,bitmapFilename).getAbsolutePath());
mBitmapCache.put(位图文件名,ret);
}
返回ret;
}
/**
*清除位图缓存
*/
公共空间清除(){
if(mbitMacache!=null){
用于(位图位图:mbitMacache.values()){
if(bitmap!=null)bitmap.recycle();
}
mBitmapCache.clear();
}
}
}

您多久调用一次_renderImage()?很多。想象一下画在画布上的瓷砖(图像块)。这很有意义。但我唯一能做的就是用这种方法。如果我在“drawBitmap”调用之后进行回收,我仍然会从画布中得到错误。。。