【问题标题】:How to fix a "java.lang.OutOfMemoryError: bitmap size exceeds VM budget " error on android如何修复 Android 上的“java.lang.OutOfMemoryError:位图大小超出 VM 预算”错误
【发布时间】:2010-08-27 21:32:27
【问题描述】:

我已经多次看到这个问题被问到,但没有一个答案对我正在做的事情真正有意义...... 我有一个安卓游戏(参见google source control的源代码) 这是一个纸牌游戏,我使用了一种每轮重画每手牌的方法——这可能很浪费,但我想不出更好的方法来做到这一点。 下面是 redrawHand 方法的代码:

private void redrawHand(Hand hand) {
  ImageView[] cardView = hand.getCardsViews();
  View container = hand.getContainer();
  for (int i = 0; i < GameData.YANIV_NUM_CARDS; i++) {
   PlayingCard card = hand.getCardByLocation(i);
   if (card != null) {
    // Show Card
    cardView[i].setVisibility(View.VISIBLE);
    int resId;
    if (hand.shouldCardsBeShown()) {
     resId = card.getImageResourceId();
    } else {
     resId = R.drawable.back;
    }
    cardView[i].setImageResource(resId);
// TODO: Disgusting patch, need to fix asap!!!
if (hand.isHumanPlayer()) {
 // Show isSelected
 // when selected, move up 15 pixels
 boolean isSelected = hand.isCardSelected(i);
 ((LinearLayout.LayoutParams) cardView[i].getLayoutParams()).bottomMargin = isSelected? 15 : 0;
}   } else {
cardView[i].setVisibility(View.INVISIBLE);   }  }  // Set player name hand.getHandLabelView().setText(hand.getHandLabel());  container.requestLayout(); }

安装 ACRA (http://code.google.com/p/acra/wiki/ACRAHowTo) 后,我开始收到来自声称以下内容的设备的崩溃报告:

java.lang.OutOfMemoryError: 位图大小超出 VM 预算 在 android.graphics.BitmapFactory.nativeDecodeAsset(本机方法) 在 android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:363) 在 android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:212) 在 android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:673) 在 android.content.res.Resources.loadDrawable(Resources.java:1639) 在 android.content.res.Resources.getDrawable(Resources.java:535) 在 android.widget.ImageView.resolveUri(ImageView.java:541) 在 android.widget.ImageView.setImageResource(ImageView.java:293) 在 com.geekadoo.ui.Yaniv.redrawHand(Yaniv.java:765) 在 com.geekadoo.ui.Yaniv.performYaniv(Yaniv.java:539) 在 com.geekadoo.ui.Yaniv.performYanivHandler(Yaniv.java:503) 在 com.geekadoo.ui.Yaniv.access$1(Yaniv.java:502) 在 com.geekadoo.ui.Yaniv$2.onClick(Yaniv.java:323) 在 android.view.View.performClick(View.java:2196) 在 android.view.View.onTouchEvent(View.java:3849) 在 android.widget.TextView.onTouchEvent(TextView.java:6376) 在 android.view.View.dispatchTouchEvent(View.java:3385) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:872) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:872) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:872) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:872) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:872) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:872) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:872) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:872) 在 com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1764) 在 com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1213) 在 android.app.Activity.dispatchTouchEvent(Activity.java:2066) 在 com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1748) 在 android.view.ViewRoot.handleMessage(ViewRoot.java:1561) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java:123) 在 android.app.ActivityThread.main(ActivityThread.java:3977) 在 java.lang.reflect.Method.invokeNative(Native Method) 在 java.lang.reflect.Method.invoke(Method.java:521) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:540) 在 dalvik.system.NativeStart.main(Native Method)

我无法理解为什么会发生这种情况 - 是否存在内存泄漏?我应该以某种方式释放我缺少的东西吗? 请帮助,有很多人因此无法享受这个免费的开源游戏。 谢谢!

【问题讨论】:

  • 当我在 MapView 上快速放大时,我不断得到它。我看到 Romain Guy(谷歌工程师)的回答,几乎说你使用了太多的内存,要修复它,你只需要使用更少的内存。您分配了太多的大位图,因此会引发错误。不是很具体,但这里可能就是这种情况。如果您编辑帖子并正确格式化,我会详细阅读您的代码。
  • 正如您在我的谷歌代码中看到的那样,我没有使用大位图,我怀疑内存泄漏但无法弄清楚为什么会发生......

标签: android memory memory-leaks out-of-memory


【解决方案1】:

从堆栈跟踪中,您可以看到作为 redrawHand 中 setImageResource() 调用的副作用,正在分配位图。

一般来说,像这样的位图和资源应该在启动时分配一次,而不是在每次重绘时分配。如果您在 onCreate(或 onResume?)中加载图像资源,然后在重绘期间引用这些资源,我认为您将避免该错误。

我并不完全清楚为什么这会表现为内存泄漏。从技术上讲,如果您分配新的位图内存来支持视图,则应该释放旧内存。也许 GC 在某些系统上落后了,无法跟上您分配新位图的速度?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-29
    • 2012-08-19
    • 2011-04-26
    相关资源
    最近更新 更多