2016-12-03 132 views
0
private class Roller implements Runnable 
{ 
    private long delayMillis; 

    public Roller(long delayMillis) 
    { 
     this.delayMillis = delayMillis; 
    } 

    @Override 
    public void run() 
    { 
     if (tv != null) 
     { 
      int min = 0; 
      int max = 3; 
      int n = rand.nextInt(max - min + 1) + min; 
      String roll = String.valueOf(n); 
      tv.setText("Random number is " + roll); 

      if (roll.equals("0")) { 
       ibRed.setImageResource(R.drawable.red_selector); 
       ibGreen.setImageResource(R.drawable.green_dark); 
       ibBlue.setImageResource(R.drawable.blue_dark); 
       ibYellow.setImageResource(R.drawable.yellow_dark); 
      } 
      if (roll.equals("1")) { 
       ibRed.setImageResource(R.drawable.red_dark); 
       ibGreen.setImageResource(R.drawable.green_selector); 
       ibBlue.setImageResource(R.drawable.blue_dark); 
       ibYellow.setImageResource(R.drawable.yellow_dark); 
      } 
      if (roll.equals("2")) { 
       ibRed.setImageResource(R.drawable.red_dark); 
       ibGreen.setImageResource(R.drawable.green_dark); 
       ibBlue.setImageResource(R.drawable.blue_selector); 
       ibYellow.setImageResource(R.drawable.yellow_dark); 
      } 
      if (roll.equals("3")) { 
       ibRed.setImageResource(R.drawable.red_dark); 
       ibGreen.setImageResource(R.drawable.green_dark); 
       ibBlue.setImageResource(R.drawable.blue_dark); 
       ibYellow.setImageResource(R.drawable.yellow_selector); 
      } 

      tv.postDelayed(this, delayMillis); 
     } 
    } 
} 

在運行上面的代碼中的活動,有一段時間我收到以下錯誤後:如何防止內存溢出異常的Runnable的

E/AndroidRuntime: FATAL EXCEPTION: main 
    Process: com.myapp, PID: 4601 
    java.lang.OutOfMemoryError: Failed to allocate a 12960012 byte allocation with 1400312 free bytes and 1367KB until OOM 
     at dalvik.system.VMRuntime.newNonMovableArray(Native Method) 
     at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) 
     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:609) 
     at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444) 
     at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:973) 
     at android.content.res.Resources.loadDrawableForCookie(Resources.java:2453) 
     at android.content.res.Resources.loadDrawable(Resources.java:2360) 
     at android.content.res.Resources.getDrawable(Resources.java:768) 
     at android.support.v7.widget.ResourcesWrapper.getDrawable(ResourcesWrapper.java:133) 
     at android.content.Context.getDrawable(Context.java:402) 
     at android.support.v4.content.ContextCompatApi21.getDrawable(ContextCompatApi21.java:26) 
     at android.support.v4.content.ContextCompat.getDrawable(ContextCompat.java:344) 
     at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:197) 
     at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:185) 
     at android.support.v7.content.res.AppCompatResources.getDrawable(AppCompatResources.java:100) 
     at android.support.v7.widget.AppCompatImageHelper.setImageResource(AppCompatImageHelper.java:69) 
     at android.support.v7.widget.AppCompatImageButton.setImageResource(AppCompatImageButton.java:69) 
     at com.myapp.MainActivity$Roller.run(MainActivity.java:85) 
     at android.os.Handler.handleCallback(Handler.java:739) 
     at android.os.Handler.dispatchMessage(Handler.java:95) 
     at android.os.Looper.loop(Looper.java:135) 
     at android.app.ActivityThread.main(ActivityThread.java:5253) 
     at java.lang.reflect.Method.invoke(Native Method) 
     at java.lang.reflect.Method.invoke(Method.java:372) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 

什麼是避免,最好的方法是什麼?繪圖每個大約26KB。

+0

當您收到OOM錯誤時,問題在系統範圍內。它通常不是你現在分配的東西,這是問題(除非它是巨大的),它通常是你的應用程序其他地方的泄漏。 –

+0

我應該發佈整個活動代碼嗎? – Si8

+0

您需要生成一些堆轉儲並找出內存中的內容。內存泄漏通常很難從代碼單獨調試。 –

回答

2

從您發佈的代碼中,似乎setImageResource每次調用時都會解碼圖像資源。

的函數調用Android的文件說 -

void setImageResource (int resId)

Sets a drawable as the content of this ImageView.

This does Bitmap reading and decoding on the UI thread, which can cause a latency hiccup. If that's a concern, consider using setImageDrawable(android.graphics.drawable.Drawable) or setImageBitmap(android.graphics.Bitmap) and BitmapFactory instead.

既然你多次調用功能,這可能是你的內存溢出異常的原因,如果你的圖片資源是非常大的。

我建議您保留解碼圖像資源的靜態副本,並使用setImageDrawable而不是setImageResource函數調用。

您可以修改你的類來保存你的可繪製的靜態實例如圖所示 -

private class Roller implements Runnable 
{ 
    private long delayMillis; 
    private static Drawable lRedDark = null; 
    private static Drawable lRedSelector = null; 
    private static Drawable lGreenDark = null; 
    private static Drawable lGreenSelector = null; 
    private static Drawable lBlueDark = null; 
    private static Drawable lBlueSelector = null; 
    private static Drawable lYellowDark = null; 
    private static Drawable lYellowSelector = null; 

    public Roller(long delayMillis) 
    { 
     this.delayMillis = delayMillis; 
    try 
    { 
    if(Roller.lRedSelector == null) 
    { 
     lRedSelector = getResources().getDrawable(R.drawable.red_selector); 
    } 

    if(Roller.lRedDark == null) 
    { 
     lRedDark = getResources().getDrawable(R.R.drawable.red_dark); 
    } 
    //Load all other drawables here .... 
    } 
    catch(Exception ex) 
    { 
     Log.e("ERR","Failed to load drawable - " + ex.getLocalizedMessage()); 
    } 
    } 

然後修改您的顯示代碼 -

if (roll.equals("0")) { 
      ibRed.setImageDrawable(Roller.lRedSelector); 
      ibGreen.setImageDrawable(Roller.lGreenDark); 
      ibBlue.setImageDrawable(Roller.lBlueDark); 
      ibYellow.setImageDrawable(Roller.lYellowDark); 
     } 

和類似。

我希望這能解決您的問題。

+0

謝謝你的迴應。當我在家時我會測試它。 – Si8

+0

謝謝,但我最終做的是做一個Runnable方法,並使用一個處理程序而不是TextView作爲後期和postdelayed,我沒有這個問題了。 – Si8

1

保留副本引用的一種替代方法是實際在每個位置渲染它們。然後,改變你實際想要展示的那個的可見性。

setVisibility(View.INVISIBLE)

Android hide and removing the image in imageview

只是改變了知名度並不需要給他們分配更多的內存。