我有一个显示很多活动的应用程序,每个活动都显示一个适合屏幕宽度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)
我不知道这里出了什么问题,我正在做位图的循环(),我也尝试使用和不使用System.gc(),在这两种情况下我都遇到了崩溃
答案 0 :(得分:2)
它是known bug,这不是因为大文件。由于Android缓存Drawables,因此在使用少量图像后内存不足。但我通过跳过Android默认缓存系统找到了它的替代方式。
<强> Soultion 强>: 在Assets中创建一个drawable文件夹,并将图像移动到资源中的“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"
答案 1 :(得分:1)
使用DDMS获取堆转储,并使用Eclipse Memory Analyzer(内置于Eclipse ADT中或可以独立运行)对转储进行一些分析。您寻找的是您分配但未被释放的对象。一种可能性是你正在泄露活动。您说在启动12-13活动后发生OOM错误。一次只能看到其中一项活动,以便您可以从onPause()
或onStop()
方法中的已暂停活动中释放内存。再次,分析堆转储将使您更好地了解占用堆内存的原因。
仅供参考 - Bitmap #recycle()仅适用于Gingerbread和更低版本的设备。在较新版本的操作系统上,位图存储在堆上,并像其他对象一样被垃圾收集。请参阅本文档中的“在Android 2.3.3及更低版本上管理内存”部分:https://developer.android.com/training/displaying-bitmaps/manage-memory.html