2016-12-03 133 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

只是改变了知名度并不需要给他们分配更多的内存。