Как предотвратить ошибку «Недостаточно памяти» в кэшировании LRU Android

Я использовал кэширование памяти LRU для кэширования растровых изображений в моем приложении для Android. Но после того, как некоторые растровые изображения загружены в приложение карты LRU, приложение закрывается, говоря об исключении из памяти. Я провел за этим целый день, но еще не нашел решения, пожалуйста, кто-нибудь может мне помочь. Я сильно застрял в этой проблеме. Заранее спасибо.

ВОТ МОЙ КОД

final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024);
final int cacheSize = maxMemory / 8;
bitmapHashMap = new LruCache<String, Bitmap>(cacheSize)
{
@SuppressLint("NewApi")
@Override
protected int sizeOf(String key, Bitmap value)
{
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB_MR2)
{
return value.getByteCount()/1024;
}
else
{
return (value.getRowBytes() * value.getHeight())/1024;
}
}
};

person Ravi    schedule 20.02.2014    source источник


Ответы (4)


Если ваше приложение использует android:largeheap="true",

Никогда не используйте Runtime.getRuntime().maxMemory(), так как вы, скорее всего, будете использовать больше памяти, чем доступно, и чаще OOM, вместо этого используйте класс памяти и рассчитайте размер кеша следующим образом:

    /** Default proportion of available heap to use for the cache */
    final int DEFAULT_CACHE_SIZE_PROPORTION = 8;

    ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    int memoryClass = manager.getMemoryClass();
    int memoryClassInKilobytes = memoryClass * 1024;
    int cacheSize = memoryClassInKilobytes / DEFAULT_CACHE_SIZE_PROPORTION;
    bitmapHashMap = new LruCache<String, Bitmap>(cacheSize)
person petey    schedule 20.02.2014
comment
я использовал то же самое, но он дает ту же ошибку нехватки памяти, это потому, что изображения не перерабатываются или что ?? Lru не выполняет эту переработку по умолчанию??? - person Ravi; 21.02.2014
comment
Каково значение DEFAULT_CACHE_SIZE_PROPORTION, поскольку я не могу найти никаких ссылок на него. - person Theo; 26.02.2014
comment
что, если ваше приложение не использует largeHeap=true? - person Adam Johns; 14.05.2014
comment
проверьте загружаемое растровое изображение и трассировку стека, обычно он сообщает вам об ограничении памяти и попытке разрешить требуемую память, необходимую во время bOOM. - person petey; 14.05.2014

Out of Memory Exception возникает, когда растровые изображения превышают доступную виртуальную память, хорошей практикой является повторное использование растровых изображений.

  bitmap.recycle();

Подробнее здесь

Когда следует перерабатывать растровое изображение с помощью LRUCache?

на вопрос ответил г-н Марк Мерфи.

person Jorgesys    schedule 20.02.2014
comment
Lru не может выполнять эти переработку по умолчанию самостоятельно или что??? обязательно ли выполнять эту переработку вручную в коде??? - person Ravi; 21.02.2014

Вы следовали этому руководству? http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html Это хороший учебник, чтобы узнать, как реализовать хранение растровых изображений.

person Substitut    schedule 20.02.2014
comment
да, я ссылался на тот же документ для кэширования памяти, но он дает мне ошибку нехватки памяти. Это потому, что изображения не перерабатываются или что? мне нужно переработать эти растровые изображения в карте lru вручную?? - person Ravi; 21.02.2014
comment
Вы должны комбинировать использование LRU Cache с набором soffReference‹Bitmap›. Класс SoftReference автоматически удалит экземпляр растрового изображения, прежде чем возникнет исключение нехватки памяти. - person Substitut; 21.02.2014

вам нужно будет очистить кеш и загрузить снова, когда вы получите Exception . Проверьте ниже функцию, чтобы очистить кеш, когда память превышает

    private Bitmap getBitmap(String url)
            {
     File f=fileCache.getFile(url);
     //from SD cache
    Bitmap b = decodeFile(f);
    if(b!=null)
        return b;

    //from web
    try {
        Bitmap bitmap=null;
      //  URL imageUrl = new URL(url);

        /***/

        HttpURLConnection conn = null;
        URL imageUrl = new URL(url);
        if (imageUrl.getProtocol().toLowerCase().equals("https")) {
            trustAllHosts();
            HttpsURLConnection https = (HttpsURLConnection) imageUrl.openConnection();
            https.setHostnameVerifier(DO_NOT_VERIFY);
            conn = https;
        } else {
            conn = (HttpURLConnection) imageUrl.openConnection();
        }
        /***/



       // HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
        conn.setConnectTimeout(30000);
        conn.setReadTimeout(30000);
        conn.setInstanceFollowRedirects(true);
        InputStream is=conn.getInputStream();
        OutputStream os = new FileOutputStream(f);
        Utils.CopyStream(is, os);
        os.close();
        bitmap = decodeFile(f);
        return bitmap;
    } catch (Throwable ex){
       ex.printStackTrace();
       if(ex instanceof OutOfMemoryError)
           memoryCache.clear();
       return null;
    }
}
person Gopal Sharma    schedule 06.08.2014