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

发布于 2024-12-04 06:58:46 字数 682 浏览 0 评论 0原文

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

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

我尝试过回收图像,但画布却无法处理回收的位图。

任何解决方案将不胜感激。

I have an map app. Somewhere in my code I am rendering data from database into canvas.
I ran into "out of memory" exception and I cant figure out how to avoid it.

Here is the relevant method. I get exception when creating bitmap with 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);
}

I have tried recycling the image, but then the canvas coplains it cant work with recycled bitmaps.

Any solution would be much apreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

若有似无的小暗淡 2024-12-11 06:58:46

我建议有一个位图缓存。即使回收预蜂窝上的图像也需要时间来释放内存(位图数据存储在不由 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();
        }
    }
}

I would suggest having a bitmap cache. Even recycling images on pre-honeycomb takes time to free memory (Bitmap data is stored in native memory that is not directly managed by dalvik). Here is a sample of a bitmap cache. Please adjust it to your needs.

/**
 * @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();
        }
    }
}
意中人 2024-12-11 06:58:46

我尝试过回收图像,但画布却无法处理回收的位图。

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

以下是 javadoc 关于 recycle() 的说法:

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

I have tried recycling the image, but then the canvas coplains it cant work with recycled bitmaps.

I think that the idea is that you are supposed to "recycle" the bitmap and then drop it on the floor for the garbage collector to deal with.

Here's what the javadoc says about recycle():

"Free the native object associated with this bitmap, and clear the reference to the pixel data. This will not free the pixel data synchronously; it simply allows it to be garbage collected if there are no other references. The bitmap is marked as "dead", meaning it will throw an exception if getPixels() or setPixels() is called, and will draw nothing. This operation cannot be reversed, so it should only be called if you are sure there are no further uses for the bitmap. This is an advanced call, and normally need not be called, since the normal GC process will free up this memory when there are no more references to this bitmap.".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文