android - 启用 largeHeap 的位图回收

标签 android android-image android-memory android-largeheap

在启用 largeHeap 选项之前,我正在处理大型位图,它几乎消耗了应用程序可用的全部内存,并通过导航回收它并加载新的内存,几乎在整个可用堆上工作。但是,当某些操作需要更多内存时,应用程序会崩溃。所以我启用了 largeHeap=true 以获得更多内存。

但是这样做有一个意想不到的行为,看起来位图的 recycle() 方法大部分时间都不起作用,并且在 58Mb 内存中工作的应用程序(有时超过抛出OutOfMemoryException) 现在以指数方式消耗内存并保持增长(目前我所做的测试达到 231Mb 分配内存),预期的行为是内存管理保持工作并且应用程序不会使用超过 60Mb。

我怎样才能避免这种情况?还是有效地回收位图?

编辑:实际上,当在设备上分配超过 390Mb 的内存时,我让它给出一个 OutOfMemoryError。 阅读 GC_* 日志显示只有 GC_FOR_ALLOC 有时释放了 3.8Mb,但几乎没有其他 GC 运行释放了一些东西。

最佳答案

你应该看看Displaying 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;

这将在下载之前为您提供图像的大小,在此基础上您可以检查设备的大小并使用 calculateInSampleSize()decodeSampledBitmapFromResource() 在文档的解释中给出。

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

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);

你可以设置inSampleSize,

 options.inSampleSize = inSampleSize;

最后一定要打电话,

options.inJustDecodeBounds = false;

否则它将返回 Bitmap 作为 null

  • 脱离 UI 线程处理位图

    在 UI 线程上处理位图从来都不安全,因此最好在后台线程中执行此操作并在处理完成后更新 UI。

  • 缓存位图

    LruCache可从 API 12 获得,但如果您有兴趣使用以下版本,它也可在 Support Library 中获得也。因此,应该使用它有效地缓存图像。您也可以使用 DiskLruCache对于您希望在外部存储中保留更长时间的图像。

  • 清除缓存

    有时,当您的图片太大时,即使缓存图片也会导致 OutOfMemoryError,因此在这种情况下,最好在图片超出范围或长时间不使用时清除缓存,这样可以缓存其他图像。

    我已经为此创建了一个演示示例,您可以从here 下载

关于android - 启用 largeHeap 的位图回收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12716574/

相关文章:

java - 将 multidex apk 部署到 Fabric Beta 时出现 android ART NoClassDefFoundError

Android ViewPager 和 ListViews

android - 找不到处理 Intent twitter android 的 Activity

android - 如何将字符串与图像连接起来

Android 错误 : java. lang.OutOfMemoryError: bitmap size exceeds VM budget

java - Google Map v2 缩放以适合所有标记和多段线

android - 用opencv处理Android图像

android - 如何更改 TabHost 中的选项卡图像

android - 当应用程序在后台运行时,Android 能否在不终止整个进程的情况下终止 Activity ?

android - 取消绑定(bind) drawables onPause() 导致无响应的后退导航并跳过此步骤导致内存溢出