2010-08-27 111 views
2

我見過這個問題很多次被問過,但沒有一個答案真的在我所做的事情中有意義... 我有一個安卓遊戲(看源碼google source control) 這是一款紙牌遊戲,我使用了一種每輪都重新繪製每一隻手的方法 - 這可能是浪費,但我想不出一個更好的方法來做到這一點。 下面是redrawHand方法的代碼:如何解決「java.lang.OutOfMemoryError:位圖大小超過虛擬機預算」的錯誤android

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: bitmap size exceeds VM budget at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:363) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:212) at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:673) at android.content.res.Resources.loadDrawable(Resources.java:1639) at android.content.res.Resources.getDrawable(Resources.java:535) at android.widget.ImageView.resolveUri(ImageView.java:541) at android.widget.ImageView.setImageResource(ImageView.java:293) at com.geekadoo.ui.Yaniv.redrawHand(Yaniv.java:765) at com.geekadoo.ui.Yaniv.performYaniv(Yaniv.java:539) at com.geekadoo.ui.Yaniv.performYanivHandler(Yaniv.java:503) at com.geekadoo.ui.Yaniv.access$1(Yaniv.java:502) at com.geekadoo.ui.Yaniv$2.onClick(Yaniv.java:323) at android.view.View.performClick(View.java:2196) at android.view.View.onTouchEvent(View.java:3849) at android.widget.TextView.onTouchEvent(TextView.java:6376) at android.view.View.dispatchTouchEvent(View.java:3385) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:872) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:872) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:872) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:872) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:872) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:872) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:872) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:872) at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1764) at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1213) at android.app.Activity.dispatchTouchEvent(Activity.java:2066) at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1748) at android.view.ViewRoot.handleMessage(ViewRoot.java:1561) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:123) at android.app.ActivityThread.main(ActivityThread.java:3977) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:521) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:540) at dalvik.system.NativeStart.main(Native Method)

我無法理解爲什麼這發生了 - 有沒有內存泄漏?我應該以某種方式發佈我失蹤的東西嗎? 請幫忙,有很多人因此無法享受這個免費的開源遊戲。 謝謝!

+0

當我在MapView上快速放大時,我總是這樣做。我看到Romain Guy(Google工程師)的一個回答,那就是說你使用的內存太多,修復它只需要少用一點。你有太多的大Bitmaps分配,並因此拋出一個錯誤。不是很具體,但這可能是這種情況。如果你編輯你的文章並正確格式化,我會更多地閱讀你的代碼。 – 2010-08-28 00:03:06

+0

正如你可以看到我的代碼在谷歌代碼,我沒有使用大的位圖,我懷疑內存泄漏,但無法弄清楚爲什麼會發生... – ekatz 2010-08-30 16:16:23

回答

0

從堆棧跟蹤中,您可以看到一個位圖被分配爲redrawHand中setImageResource()調用的副作用。

通常,像這樣的位圖和資源應該在啓動時分配一次,而不是在每次重繪時分配一次。如果您在onCreate(或onResume?)中加載圖像資源,然後在重繪期間引用這些資源,我認爲您將避免該錯誤。

我不完全清楚爲什麼這表現爲內存泄漏。從技術上講,如果你分配新的位圖內存來支持View,舊內存應該被釋放。也許GC在某些系統上落後了,無法跟上你分配新位圖的速度?

相關問題