位图的循环使用largeHeap启用 [英] Bitmap recycle with largeHeap enabled

查看:278
本文介绍了位图的循环使用largeHeap启用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在启用 largeHeap 选项,我正在处理大量的位图,它是消耗了几乎整个可用的应用程序内存,和回收过来导航和加载新的工作一轮几乎全堆可用。然而,当某些操作需要更多的内存的应用程序崩溃。所以我启用 largeHeap = TRUE 来有了更多的内存。

但这样做有一个意外的行为,它看起来像循环()位图的方法,不工作的大部分时间,而工作内存在58MB的应用(和超过有时投掷 OutOfMemoryException异常)现在消耗内存指数和不断增加(目前的测试,我做了来到231Mb分配的内存),预期的行为是内存管理保持工作,比60MB的应用程序将无法使用了。

我怎样才能避免这种情况?或者有效回收位图?

编辑:其实,我做了给一个的OutOfMemoryError 时,以上的内存设备上390MB分配更多。 阅读GC_ *显示日志表明解除3.8MB只有GC_FOR_ALLOC的时候,但是几乎没有其他GC运行中解脱出来的东西。

解决方案

您也许应该看看的显示位图有效地,其中包括几种方法可以处理大位图高效,

  • 装载大型高效位图

  BitmapFactory.Options选项=新BitmapFactory.Options();
options.inJustDe codeBounds = TRUE;
BitmapFactory.de codeResource(getResources(),R.id.myimage,期权);
INT imageHeight = options.outHeight;
INT ImageWidth等= options.outWidth;
 

这会给你的图像的大小在下载前,并在此基础上,你可以检查你的设备的大小,并使用它的规模 calculateInSampleSize()德codeSampledBitmapFromResource()给出文档的说明。

计算多少,我们需要将图像缩放,

 如果(imageHeight> reqHeight || ImageWidth等> reqWidth){
      如果(ImageWidth等> imageHeight){
          inSampleSize = Math.round((浮点)imageHeight /(浮点)reqHeight);
      } 其他 {
          inSampleSize = Math.round((浮点)ImageWidth等/(浮点)reqWidth);
      }
    }
 

  INT inSampleSize = Math.min(ImageWidth等/ reqWidth,imageHeight / reqHeight);
 

在你可以设置 inSampleSize

  options.inSampleSize = inSampleSize;
 

后来终于确定你打电话,

  options.inJustDe codeBounds = FALSE;
 

否则将返回位图作为

  • 处理位图关在UI线程

    处理位图UI线程上是从来没有安全所以它总是好做,在后台线程和更新用户界面的过程完成之后。

  • 缓存位图

    LruCache 可从API 12,但如果你有兴趣它使用下面的版本中,它也可以在支持库太。所以,应该做有效使用的图像缓存。你也可以使用 DiskLruCache 为您希望再留在extenal储存较长时间的图像。

  • 清除缓存

    有时候,当你的图像尺寸过大,甚至缓存图像原因的OutOfMemoryError 因此,在这种情况下,它能够更好地清除缓存当图像超出范围或不用于更长的时间,使其他图像可以被缓存。

    我已经创造了同一个演示的例子,你可以从这里下载

Before enabling largeHeap option, I was handling large bitmaps and it's consume almost the entire memory available for the application, and recycling it over navigation and loading new ones works round on almost the full heap available. However when some operations needs a bit more memory the application crashes. So I enabled largeHeap=true to have a bit more memory.

But doing this has a unexpected behavior, it's looks like that recycle() method of bitmaps do not work most of times, and the application that worked in 58Mb of memory (and exceeds sometimes throwing a OutOfMemoryException) now consumes memory exponentially and keeps growing (for now the test I did came to 231Mb allocated memory), the expected behavior is that the memory management keeps working and the application will not use more than 60Mb.

How can I avoid that? Or efficiently recycle bitmaps?

EDIT: Actually, I made it give a OutOfMemoryError when allocating more than 390Mb of memory on the device. Reading GC_* logs shown that only GC_FOR_ALLOC that freed 3.8Mb sometimes, but almost never other GC runs freed something.

解决方案

You should probably have a look at Displaying Bitmaps Efficiently which includes several ways to handle large Bitmaps Efficiently,

  • Loading Large Bitmaps Efficiently

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;

This will give you the size of the image before downloading and on that basis you can check the size of your device and scale it using calculateInSampleSize() and decodeSampledBitmapFromResource() given in the explanation of docs.

Calculating how much we need to scale the image,

if (imageHeight > reqHeight || imageWidth > reqWidth) {
      if (imageWidth > imageHeight ) {
          inSampleSize = Math.round((float)imageHeight / (float)reqHeight);
      } else {
          inSampleSize = Math.round((float)imageWidth / (float)reqWidth);
      }
    }

int inSampleSize = Math.min(imageWidth / reqWidth,imageHeight / reqHeight);

The you can set the inSampleSize,

 options.inSampleSize = inSampleSize;

Then finally make sure you call,

options.inJustDecodeBounds = false;

else it will return Bitmap as null

  • Processing Bitmaps Off the UI Thread

    Processing Bitmap on UI thread is never safe so its always better to do that in a background thread and update UI after the process is completed.

  • Caching Bitmaps

    LruCache is available from API 12 but if you are interested it using below versions it is also available in Support Library too. So caching of Images should be done efficiently using that. Also you can use DiskLruCache for images where you want then to remain for longer period in extenal storage.

  • Clearing the Cache

    Sometimes when your image size is too large even caching the image causes OutOfMemoryError so in that case its better to clear the cache when your image is out of the scope or not used for longer period so that other images can be cached.

    I had created a demo example for the same, you can download from here

这篇关于位图的循环使用largeHeap启用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆