2012-09-14 64 views
5

挫折崗位....android CountDownTimer - 最後onTick沒有調用 - 使用什麼乾淨的解決方案?

我只是偶然發現了「CountDownTimer - 最後onTick沒有叫」的問題,許多人在這裏報道。

簡單的演示顯示問題

package com.example.gosh; 

import android.app.Activity; 
import android.os.Bundle; 
import android.os.CountDownTimer; 
import android.util.Log; 

public class CountDownTimerSucksActivity extends Activity { 

int iDontWantThis = 0; // choose 100 and it works yet ... 

private static final String TAG = "CountDownTimerSucksActivity"; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    new MyCountDownTimer(10000 + iDontWantThis , 1000).start(); 
} 

class MyCountDownTimer extends CountDownTimer { 

    long startSec; 

    public MyCountDownTimer(long millisInFuture, long countDownInterval) { 
     super(millisInFuture, countDownInterval); 
     // TODO Auto-generated constructor stub 
     startSec = System.currentTimeMillis() ; 
    } 

    @Override 
    public void onFinish() { 
     // TODO Auto-generated method stub 
     Log.e(TAG, " onFinish (" + getSeconds() + ")"); 
    } 

    @Override 
    public void onTick(long millisUntilFinished) { 
     // TODO Auto-generated method stub 
     Log.e(TAG, millisUntilFinished + " millisUntilFinished" + " (" + getSeconds() + ")"); 

    } 

    protected long getSeconds() { 
     return (((System.currentTimeMillis() - startSec)/1000) % 60); 

    } 

} 

} 

從試運行輸出的logcat的......

logcat ouput

正如你所看到的最後一次通話onTick與1963ms millisUntilFinished發生,那麼,接下來的通話在接近2秒後完成。當然是一個馬車行爲。我在這個尚未清潔的解決方案中發現了很多帖子。一個我包含在源代碼中,如果你將iDontWantThis字段設置爲100,它就可以工作。

我不介意在次要領域的解決方法,但這似乎是一個核心功能,我不知道它尚未修復。你們在做什麼來爲此做一個乾淨的解決方案?

非常感謝

馬丁

UPDATE:

由薩姆CountDownTimer的一個非常有用的修正,它不會在最後一跳surpresses由於內部毫秒的延遲,還可以防止積聚ms延遲隨着時間的推移可以發現here

回答

8

您遇到的行爲實際上是明確定義在CountdownTimer代碼; have a look at the source

通知在handleMessage()的內部,如果剩餘時間少於間隔,它明確不會呼叫onTick(),只是延遲,直到完成。

但是,請注意,CountdownTimer只是Handler上的一個非常薄的包裝,它是Android框架的實時定時組件。作爲一種解決方法,您可以非常輕鬆地從此源創建自己的計時器(少於150行),並刪除此限制以獲得最終的滴答回調。

+0

非常感謝,很新的Android和我還沒有做的步驟其實看看它的源代碼,在這樣的情況下。非常感謝我指出了這一步。我會按照建議實現我自己的CountDownTimer,如果millisUntilFinished> 0,我總是可以調用onTick,並且如果剩下的millis允許我想做的事情,我可以很容易地檢查(實際上,我只需要倒數計時器,它顯示6,5,4,3,2 ,1,0) – dorjeduck

+0

只是爲了完整起見,刪除下面的其他內容,如果block做的工作有ontick調用,只要有millis左邊------------------- ---------------------------------------------} else if(millisLeft dorjeduck

2

我覺得挫折來自對滴答應該是什麼不正確的期望。正如另一個答案指出的那樣,這種行爲是有意的。處理這種情況的另一種可能方法是簡單地指定一個較小的間隔。例如,如果您正在實施某種倒數計時器,則將間隔時間更改爲500毫秒並不會造成什麼影響。如果重要的是某些工作只在秒數發生變化時完成,那麼您也可以通過將getSeconds()只有在價值發生變化時才做這項工作。

如果CountdownTimer改爲始終火,即使剩餘時間小於間隔最後一跳,我敢肯定的StackOverflow將有一大堆的問題,如「爲什麼我沒有足夠的時間的最後一跳CountdownTimer?「

+0

你是對的我只是期望不同的行爲,這是挫折的根源。我很驚訝它在API文檔中沒有提到的預期行爲,特別是在上面的logcat中,可以看到倒數計時器實際上是「遲到」,因爲它比給定秒數左/間隔晚47毫秒,那非常47ms導致onTick不被稱爲我期待它。想象一下你給了4個小時作爲intervall的情況,誰會期望onTick不會因爲43ms而被呼叫。但是,是的,這是與預期的問題;) – dorjeduck

1

我不明白你爲什麼說這是故意行爲,該API究竟說:

‘排定倒計時,直到在未來一段時間,對沿途的時間間隔定期通知’

new CountDownTimer(30000, 1000) { 

    public void onTick(long millisUntilFinished) { 
     mTextField.setText("seconds remaining: " + millisUntilFinished/1000); 
    } 

    public void onFinish() { 
     mTextField.setText("done!"); 
    } 
}.start(); 

,如果你設置的時間爲30秒,而countDownInterval 1000,作爲API說有規律,它應該被開除正好是30倍。 我認爲這不是故意行爲,而是一個錯誤的執行。

該解決方案應該是由Sam這裏所倡導的:

android CountDownTimer - additional milliseconds delay between ticks

+0

謝謝胡安 - 山姆的解決方案已在文章的更新中提到。 – dorjeduck

相關問題