【问题标题】:How to prevent Out of memory error in LRU Caching android如何防止LRU缓存android中的内存不足错误
【发布时间】:2014-03-21 16:14:24
【问题描述】:

我使用内存 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;
}
}
};

【问题讨论】:

    标签: android caching lru image-caching android-lru-cache


    【解决方案1】:

    您是否遵循这些指南? http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html 这是一个了解如何实现位图存储的好教程。

    【讨论】:

    • 是的,我已经为内存缓存引用了相同的文档,但它给了我内存不足的错误。是因为图像没有被回收还是什么?我需要手动回收lru map中的这些位图吗??
    • 你必须将 LRU Cache 的使用与一组 soffReference 结合起来。 SoftReference 类会在出现内存不足异常之前自动删除位图实例。
    【解决方案2】:

    如果你的应用使用 android:largeheap="true",

    永远不要使用Runtime.getRuntime().maxMemory(),因为你很可能会比availabe和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)
    

    【讨论】:

    • 我使用了相同的,但它给出了相同的内存不足错误是因为图像没有被回收还是什么? Lru 默认不执行这些回收的事情???
    • DEFAULT_CACHE_SIZE_PROPORTION 的值是多少,因为我找不到任何对它的引用。
    • 如果您的应用不使用 largeHeap="true" 怎么办?
    • 检查正在加载的位图和堆栈跟踪,它通常会告诉您内存限制和尝试允许在 bOOM 时所需的内存。
    【解决方案3】:

    Out of Memory Exception 是当位图超出可用的虚拟内存时引起的,一个好的做法是位图的回收。

      bitmap.recycle();
    

    在这里阅读更多

    When should I recycle a bitmap using LRUCache?

    马克·墨菲先生回答的问题。

    【讨论】:

    • Lru默认不能自己执行这些回收的东西还是什么???是否必须在代码中手动执行这些回收?
    【解决方案4】:

    当你得到 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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-12-30
      • 1970-01-01
      • 1970-01-01
      • 2013-01-17
      • 2012-03-07
      • 2011-12-08
      • 1970-01-01
      • 2011-07-31
      相关资源
      最近更新 更多