如何修复android上的“java.lang.OutOfMemoryError:位图大小超过VM预算”错误

时间:2010-08-27 21:32:28

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

我已经多次看过这个问题但是我所做的事情中没有一个答案真的有意义...... 我有一个安卓游戏(见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)    at 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(本地方法)

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

1 个答案:

答案 0 :(得分:0)

从堆栈跟踪中可以看到一个位图被分配为redrawHand中setImageResource()调用的副作用。

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

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