【问题标题】:Bitmap OutOfMemoryError even using recycle()位图 OutOfMemoryError 即使使用 recycle()
【发布时间】:2014-06-21 21:12:13
【问题描述】:

我有一个显示大量活动的应用程序,每个活动都显示一个适合 100% 屏幕宽度且通常超过 100% 高度的位图。

当您触摸屏幕时,会创建一个新的活动,并在之前的活动中为位图调用完成和回收:

public void clean() {
    if(this.myBitmap != null){
        Log.d(DEBUG_TAG, " Cleaning  "+this);
        this.myBitmap.recycle();
        this.myBitmap=null;
        System.gc();
    }
}

问题是所需的内存越来越大,当我启动超过 12-13 个活动时,这些消息会显示在 logcat:

05-05 16:03:02.909: I/dalvikvm-heap(24794): Clamp target GC heap from 65.790MB to 64.000MB
05-05 16:03:02.969: D/dalvikvm(24794): GC_EXPLICIT freed 71K, 5% free 59008K/61680K, paused 2ms+13ms, total 55ms
05-05 16:03:03.559: I/dalvikvm-heap(24794): Clamp target GC heap from 67.197MB to 64.000MB
05-05 16:03:03.569: D/dalvikvm(24794): GC_EXPLICIT freed 418K, 2% free 60521K/61680K, paused 3ms+28ms, total 109ms

经过更多的活动后,我遇到了这个崩溃:

05-05 16:03:05.049: E/AndroidRuntime(24794): java.lang.OutOfMemoryError
05-05 16:03:05.049: E/AndroidRuntime(24794):    at android.graphics.Bitmap.nativeCreate(Native Method)
05-05 16:03:05.049: E/AndroidRuntime(24794):    at android.graphics.Bitmap.createBitmap(Bitmap.java:809)
05-05 16:03:05.049: E/AndroidRuntime(24794):    at android.graphics.Bitmap.createBitmap(Bitmap.java:786)
05-05 16:03:05.049: E/AndroidRuntime(24794):    at android.graphics.Bitmap.createBitmap(Bitmap.java:718)

我不知道这里出了什么问题,我正在执行位图的 recycle(),并且我尝试了使用和不使用 System.gc(),在这两种情况下我都遇到了崩溃

【问题讨论】:

  • 您是否将 largeHeapSize 标志添加到您的应用程序?
  • mmmm 感谢 deathember 似乎使用它已经改进了我的应用程序,但我认为这不是最终的解决方案
  • 让我解释一下。当您在内存中使用大位图时,您将给出 OME。更多位图 - 获得 OUME 的机会更多。添加标志不是一个坏方法,因为 Android 可以让您获得最大堆大小以将对象加载到内存中。谷歌它为 Roman Guy 的 android 的内存管理。 Google 建议您使用此标志。但你有另一种方式。看看你的代码,也许你可以改进它,也许这可以修复你的 OME。

标签: android bitmap out-of-memory android-memory recycle


【解决方案1】:

它是known bug,不是因为大文件。由于 Android 缓存了 Drawables,因此在使用少量图像后内存不足。但是我通过跳过android默认缓存系统找到了替代方法。

灵魂: 在Assets中创建一个drawable文件夹,将图片移动到assets中的“drawable”文件夹中,使用下面的函数获取BitmapDrawable

public static Drawable getAssetImage(Context context, String filename) throws IOException {
    AssetManager assets = context.getResources().getAssets();
    InputStream buffer = new BufferedInputStream((assets.open("drawable/" + filename + ".png")));
    Bitmap bitmap = BitmapFactory.decodeStream(buffer);
    return new BitmapDrawable(context.getResources(), bitmap);
}

参考:https://stackoverflow.com/posts/6116316/revisions

另外,在清单文件中添加以下行

android:largeHeap="true"

【讨论】:

    【解决方案2】:

    使用 DDMS 获取堆转储并使用 Eclipse 内存分析器(内置于 Eclipse ADT 或可以独立运行)对转储进行一些分析。您正在寻找的是您分配但没有被释放的对象。一种可能性是您正在泄漏活动。你说启动12-13活动后出现OOM错误。一次只能看到一个活动,以便您可以在 onPause()onStop() 方法中从暂停的活动中释放内存。同样,分析堆转储可以让您很好地了解是什么占用了堆内存。

    仅供参考 - Bitmap#recycle() 仅在 Gingerbread 和更低的设备上才真正需要。在较新版本的操作系统上,位图存储在堆上,并像其他对象一样被垃圾收集。请参阅本文档的“在 Android 2.3.3 及更低版本上管理内存”部分:https://developer.android.com/training/displaying-bitmaps/manage-memory.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-30
      • 1970-01-01
      • 2011-10-22
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 2023-03-20
      相关资源
      最近更新 更多