Утечка памяти при создании растровых изображений в цикле - PullRequest
3 голосов
/ 14 сентября 2011

У меня есть приложение карты.Где-то в моем коде я рендеринг данных из базы данных на холст.Я столкнулся с исключением "недостаточно памяти" и не могу понять, как его избежать.

Вот соответствующий метод.Я получаю исключение при создании растрового изображения с помощью 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 ]

2 голосов
/ 14 сентября 2011

Я бы предложил иметь кэш растровых изображений.Даже переработка изображений на предварительных сотах требует времени для освобождения памяти (растровые данные хранятся в собственной памяти, которая напрямую не управляется 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 голос
/ 14 сентября 2011

Я попытался переработать изображение, но затем холст копирует, что он не может работать с переработанными растровыми изображениями.

Я думаю, что идея состоит в том, что вы должны "переработать" растровое изображениеа затем бросьте его на пол, чтобы сборщик мусора имел дело с ним.

Вот что говорит Javadoc о recycle():

"Освободите собственный объект, связанный с этим растровым изображением,и очистите ссылку на данные пикселя. Это не освободит данные пикселя синхронно, оно просто позволяет собирать мусор, если нет других ссылок. Растровое изображение помечается как «мертвое», то есть оно вызывает исключение, если getPixels() или setPixels () вызывается и ничего не рисует. Эту операцию нельзя отменить, поэтому ее следует вызывать только в том случае, если вы уверены, что для растрового изображения больше нет использования. Это сложный вызов, и обычно его не нужновызвано, поскольку обычный процесс GC освобождает эту память, когда больше нет ссылок на это растровое изображение. ".

...