安卓定时器不精确。

5
好的,我是一个刚开始学习Java和Android编程的新手。我正在尝试制作一个篮球应用程序,用于友谊比赛。现在我正在制作一个从24到0倒计时的投篮时钟,它会播放声音,并通过一个按钮进行重置。
public class MainActivity extends Activity {
    private ShotClock shotClock;
    private TextView shotClockTimer;
    private Timer timer = new Timer();
    private Button shotClockReset;
    private final static int interval = 100;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        shotClockTimer = (TextView) findViewById(R.id.shotClock);
        shotClockReset = (Button)findViewById(R.id.shotClockReset);
        shotClock = new ShotClock();
        shotClockReset.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                shotClock.shotClockReset();
            }

        });
        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                TimerMethod();
            }

        }, 0, interval);

    }

    private void TimerMethod() {
        this.runOnUiThread(Timer_Tick);
    }

    private Runnable Timer_Tick = new Runnable() {
        public void run() {
            shotClock.advanceClock();
            shotClockTimer.setText(String.format("%.1f",shotClock.getSeconds()));

        }
    };
}

这个想法是我有一个计时器,每0.1秒就会响一次,并相应地更新时钟。这个方法很好用,时钟从24开始倒数到0并且能够正确重置。但我的问题是它不准确 - 我用其他3个计时器测试了它,总是慢了一点:当其他计时器到达0时,这个计时器只剩下大约1-1.5秒左右。除了以原始方式更改间隔之外,我该怎么做才能使它更准确呢? 请友善回答,因为我是新手 :) 感谢您的帮助!

1
PS:在Java中,按照惯例,只有类/接口以大写字母开头。 - m0skit0
2个回答

8
那是因为内部调度,调度程序大约每0.1秒调用一次此方法。但是,系统本身是准确的。使用System.currentTimeMillis()来纠正这个错误。
Android本身不是实时应用程序,但系统是您可以获得的最准确的来源。
因此,在Android中编程精确的运动比赛秒表是没有用处的 ;)
只需循环并计算毫秒偏移量,如果达到偏移量,则调用方法。
但是,请考虑这里的不准确性。始终使用开始时间(1 * 0.1秒,2 * 0.1秒...)计算偏移量,而不是使用最后一个值,从而最小化不准确性。

这是正确的方法。你只需要在开始时存储System.currentTimeMillis(),并在每个间隔计算剩余时间。然后,即使你没有精确的间隔,你显示的值也是精确的。 - Schlangi
这个有效了。虽然还不是100%准确,但比以前好多了!非常感谢! - Egozy
System.currentTimeMillis是自纪元以来的毫秒数。现在想象一下这种非常糟糕的情况。你的手机在周末完全放电或者你取出了电池。通常当手机/平板电脑唤醒时,时钟会完全失效。当你有互联网连接时,时钟应该(在大多数情况下)在几秒钟后更改为正确的时间。正如你所看到的,在这种情况下,System.currentTimeMillis也会发生巨大变化。你可以添加一个BroadcastReceiver来监听Intent.ACTION_TIME_CHANGED以检测它,但我怀疑它是否足够快地触发0.1秒。 - FrankKrumnow

0
有一个我自己制作的帆船计时器也遇到了同样的问题。 使用timer.scheduleAtFixedRate代替timer.schedule。 这种方法仍然可能会导致被调度的tick产生微小的抖动,但错误不会累积,因此计时器在长时间内保持准确。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接