加载位图时出现内存不足错误

17

我有一个安卓应用,包含3个活动:

A1 --启动--> A2 --启动--> A3 --完成其过程后: 启动--> A1

(因此我不会 "finish();" 应用程序。在用户交互后,我一直使用 "startActivity(..);" 启动下一个活动)

所以这三个活动之间存在一个循环。 在每个活动中,我显示位于SD卡上的 3-9 张图片,我使用以下函数来加载这些图片:

try
{
    Uri selectedImageURI = Uri.parse(strImagePath);
    File imgFile = new  File(getRealPathFromURI(selectedImageURI, c));
    Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
    ivTmp.setImageBitmap(myBitmap);
}catch (Exception e)
{
    return null;
}

这一切都有效。

但有时(在我的活动中循环几次后),我的应用程序会崩溃。

Logcat告诉我:

01-16 13:42:15.863: DEBUG/dalvikvm(23161): GC_BEFORE_OOM freed 10K, 9% free 59019K/64400K, paused 29ms, total 30ms
01-16 13:42:15.863: ERROR/dalvikvm-heap(23161): Out of memory on a 8018704-byte allocation.
01-16 13:42:15.863: ERROR/AndroidRuntime(23161): FATAL EXCEPTION: main
        java.lang.OutOfMemoryError
        at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
        at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:502)
        at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:355)
        at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:785)
        at android.content.res.Resources.loadDrawable(Resources.java:1965)
        at android.content.res.Resources.getDrawable(Resources.java:660)
        at android.widget.ImageView.resolveUri(ImageView.java:616)
        at android.widget.ImageView.setImageResource(ImageView.java:349)
        at <MyApp>.MyActivity$6.run(MyActivity.java:143)
        at android.os.Handler.handleCallback(Handler.java:725)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:5039)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
        at dalvik.system.NativeStart.main(Native Method)

有人可以给我一些如何处理崩溃的提示吗?也许是因为我的活动被设置为状态“暂停”,而不是正确关闭它们?


1
尝试在OnPause()中调用.recycle()方法释放位图资源,并在onResume()而非onCreate()中重新加载它们。 - pumpkee
有没有更好的方法来做到这一点?比如,如果我的所有位图都位于LinearLayout中,那么调用llMain.recycle()之类的东西呢? - Prexx
你可以创建一个ArrayList<Bitmap>,将每个加载的位图添加到其中并循环回收。另一个通用的方法是:调整图像的示例大小。不知道你的应用程序是用来做什么的,但是如果只是在屏幕上简单地显示位图,大多数情况下缩小它们的示例大小仍然足够节省内存。请参见:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html - pumpkee
我也遇到过这个问题,我使用了如何解决内存溢出错误?。我认为它会对你有所帮助。 - Hardik Joshi
有没有办法从ImageButton中获取位图? - Prexx
是的。Bitmap bitmap = ((BitmapDrawable)imageButton.getDrawable()).getBitmap(); - pumpkee
4个回答

32

为了快速解决问题,您可以在清单应用程序标记中添加android:largeHeap="true"

链接在这里

我在Kindle和Nook上的表格中遇到OOM问题。

Heap size (large)
android:largeHeap="true"

规格中提到要使用更大的堆 链接在这里:

编辑: 使用缓存位图技术 链接在这里


1
这个解决方案不能防止内存溢出异常,它只是允许使用更多的内存。 - Alex Kucherenko
@AlexKucherenko 是的,正如我所提到的,这只是一个快速修复。 - Padma Kumar
@PadmaKumar 这不是“修复”,它无法解决问题。 - Manuel

2

在显示高分辨率图像时,我遇到了类似的问题。我搜索并应用了http://developer.android.com/training/displaying-bitmaps/index.html中提供的所有Android位图解决方案以及链接中的缓存机制,但它们都不起作用。没有任何正确的解决方案。然后我发现问题是:我无法正确使用可绘制文件夹结构。我将高分辨率图像保存在mdpi和hdpi文件夹中,这会导致Android将图像放大到超大尺寸。100 kb的图像会因为Android监视器/内存部分而导致内存增加20 mb。因此,我将这些超高分辨率图像添加到xxhdpi文件夹中,然后问题就突然解决了。然后我的图像滑块无缝工作。


0

我试图完成活动,但结果是我回到了一个活动。例如:我在A3上,想要去A1:我调用startIntent(A1)并finish--> 我在A2上.. :/ - Prexx
好的,我认为如果你对每个活动覆盖onStop()方法,并在该方法中加入finish()语句,那么当下一个活动启动后,应该会结束当前活动并释放资源,而不是让系统将其保留在内存中。确保finish()不会终止当前活动。 - Broo

0

这是由于您需要缩放位图的高分辨率,使用以下代码:

 Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());

    int h = 100; // height in pixels
    int w = 100; // width in pixels
Bitmap photoBitMap = Bitmap.createScaledBitmap(myBitmap,h, w, true);
ivTmp.setImageBitmap(photoBitMap);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接