Как исправить ошибку «java.lang.OutOfMemoryError: размер растрового изображения превышает бюджет виртуальной машины» на Android - PullRequest
2 голосов
/ 28 августа 2010

Я видел, как этот вопрос задавали много раз, но ни один из ответов не имел смысла в том, что я делаю ... У меня есть игра для Android (см. Источник на 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: размер растрового изображения превышает бюджет виртуальной машины на android.graphics.BitmapFactory.nativeDecodeAsset (собственный метод) на android.graphics.BitmapFactory.decodeStream (BitmapFactory.java:363) на android.graphics.BitmapFactory.decodeStreamjj (: 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) на андроиде.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:872) в android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:872) в android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:872) в android.view.ViewGroup.dispatch(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 (собственный метод) на 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 голосов
/ 27 сентября 2011

Из трассировки стека видно, что растровое изображение выделяется как побочный эффект вызова setImageResource () в redrawHand.

Как правило, растровые изображения и подобные ресурсы должны выделяться один раз, при запуске, а не при каждом перерисовке. Если вы загружаете ресурсы изображений в onCreate (или onResume?), А затем ссылаетесь на них во время перерисовки, я думаю, вы избежите ошибки.

Мне не совсем понятно, почему это проявляется как утечка памяти. Технически, если вы выделите новую растровую память для поддержки просмотра, старая память должна быть освобождена. Возможно, в некоторых системах GC отстает и не справляется со скоростью, с которой вы выделяете новые растровые изображения?

...