2017-10-08 86 views
0

我想每秒更改繪製的矩形的顏色。我有下面的代碼來做到這一點。自定義視圖忽略延遲

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); 
} 

但是,只有每隔調用postDelayed被延遲。我註銷每次調用runnable的run方法之間的毫秒數。

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 

所以每隔呼叫被推遲。任何想法爲什麼?

+0

延遲通常會有誤差範圍,如果我沒有記錯 – JoxTraex

+0

我認爲這保證這將是該時間之後,但不一定正是時候。而且,整整一秒也是一個相當大的誤差。 –

+0

你應該澄清的一件事是你所指的日誌。並顯示代碼完全是你寫的。 – JoxTraex

回答

0

使用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); 

更新:

您還可以使用線程管理器:

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

這可能會持續一段時間,但如果我想爲500毫米顯示1色,而另一個顯示爲1000則該怎麼辦?或者提供一個自定義時間計劃?這不是靈活的。 –

+0

@JBlaz動態持續時間你可以使用線程。 –

0

的問題是不是與自定義視圖。問題出在Handler。我看到你的帖子,並試圖運行一個簡單的代碼:

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); 

令人驚訝的是,它也給出了相同的結果。

結論:如果您希望功能完全相同,請不要使用處理程序。您可能需要直接使用Thread

0

看看下面的代碼我解釋過,可以通過你的測試用例。

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)