2017-10-08 3 views
0

Ich möchte die Farbe eines gezeichneten Rechtecks ​​jede Sekunde ändern. Ich habe den folgenden Code, um dies zu tun.Benutzerdefinierte Ansicht Ignorieren Verzögerung

private Runnable mRunnable; 
private int mIndex; 
... 

public BlinkingView(Context context) { 
    this(context, null); 

    mRunnable = new Runnable() { 
     @Override 
     public void run() { 
      long currentMillis = System.currentTimeMillis(); 
      Log.d("Tag", "Millis Dif -- " + (mIndex== 0 ? "GREEN" : "RED") + " :: " + (currentMillis - lastMillis)); 
      lastMillis = currentMillis; 

      // Set the paint color to be drawn. 
      mColoredRectPaint.setColor(mIndex++ % 2 == 1 ? Color.RED : Color.GREEN); 

      // Update the view. 
      invalidate(); 

      // Run again. 
      postDelayed(mRunnable, 1000); 
     } 
    }; 

    post(mRunnable); 
} 

@Override 
protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 

    // Draw the colored rectangle 
    canvas.drawRect(mLeft, mTop, mRight, mBottom, mColoredRectPaint); 

    // Draw a boarder rectangle. 
    canvas.drawRect(mStrokeLeft, mStrokeTop, mStrokeRight, mStrokeBottom, mOuterRectPaint); 
} 

Aber nur jeder zweite Anruf postDelayed verzögert. Ich melde mich die Anzahl der Millisekunden zwischen jedem Aufruf der Run-Methode des Runnable ab.

D/Tag: DURATION -- GREEN :: 1000 
D/Tag: DURATION -- RED :: 1 
D/Tag: DURATION -- GREEN :: 1002 
D/Tag: DURATION -- RED :: 3 
D/Tag: DURATION -- GREEN :: 1001 
D/Tag: DURATION -- RED :: 3 
D/Tag: DURATION -- GREEN :: 1001 
D/Tag: DURATION -- RED :: 2 

So wird jeder andere Anruf verzögert. Irgendwelche Ideen warum?

+0

Die Verzögerung wird in der Regel eine Fehlerquote haben, wenn ich mich richtig erinnere – JoxTraex

+0

ich dachte, es garantiert sie nach dieser Zeit aber nicht unbedingt sein würde genau diese Zeit. Auch eine volle Sekunde ist eine ziemlich große Fehlerspanne. –

+0

Eine Sache, die Sie klären sollten, ist Ihr Protokoll, auf das Sie sich beziehen. Und zeigen Sie den Code genau so, wie Sie ihn geschrieben haben. – JoxTraex

Antwort

0

Verwendung Timer

private Timer myTimer; 

myTimer = new Timer(); 
myTimer.schedule(new TimerTask() 
{ 
    @Override 
    public void run() 
    { 
      // Set the paint color to be drawn. 
      mColoredRectPaint.setColor(mIndex++ % 2 == 1 ? Color.RED : Color.GREEN); 

      // Update the view. 
      invalidate(); 
    } 
}, 0, 1000); 

Update:

Sie auch Thread können für Ihre Timer verwalten:

mThread=new Thread(new Runnable() { 
     @Override 
     public void run() { 

      while (!Thread.currentThread().isInterrupted()) { 

       // Set the paint color to be drawn. 
       mColoredRectPaint.setColor(mIndex++ % 2 == 1 ? Color.RED : Color.GREEN); 

       // Update the view. 
       postInvalidate(); 

       switch (state){ 
        case 1: 
         Thread.sleep(500); 
         break; 
        case 2: 
         Thread.sleep(1000); 
         break; 
        default: 
         Thread.sleep(3000); 
         break; 
       } 
      } 
     } 
    }); 
    mThread.start(); 
+0

Das könnte für eine festgelegte Dauer funktionieren, aber was, wenn ich 1 Farbe für 500 Millis und die andere für 1000 zeigen möchte? Oder bieten Sie ein benutzerdefiniertes Dauerschema an? Dies ist nicht so flexibel. –

+0

@JBlaz für dynamische Dauer können Sie Thread verwenden. –

0

Das Problem ist nicht mit der benutzerdefinierten Ansicht ist. Das Problem ist mit Handler. Ich habe Ihren Beitrag gesehen und versucht, einen einfachen Code auszuführen:

final Handler handler = new Handler(); 
mRunnable = new Runnable() { 
    @Override 
    public void run() { 
     long currentTime = System.currentTimeMillis(); 
     System.err.println(currentTime - lastTime); 
     lastTime = currentTime; 
     handler.postDelayed(mRunnable, 1000); 
    } 
}; 
handler.post(mRunnable); 

Überraschenderweise gab es auch das gleiche Ergebnis.

Fazit: Wenn Sie möchten, dass die Funktionalität genau gleich ist, verwenden Sie nicht den Handler. Vielleicht möchten Sie direkt Thread verwenden.

0

Schauen Sie sich unter Code interpretiert ich, dass Ihre Testfälle übergeben würde.

int tick = 0; 
Handler handler = new Handler(); 
handler.postDelayed(new Runnable() { 
    @Override 
    public void run() { 
     tick++; 
     if(tick%2==0) { 
      handler.postDelayed(this, 500); 
      // Set the paint color to be drawn. 
      mColoredRectPaint.setColor(Color.RED); 
     } else { 
      mColoredRectPaint.setColor(Color.GREEN); 
      handler.postDelayed(this, 1000); 
     } 
     // Update the view. 
     invalidate(); 
    } 
}, 1000) 
Verwandte Themen