2

I'm new to Android development.I want to create a stopwatch with precision of 0.01 seconds.Here is part of my code(which I think the problem lies within):

private void runTimer()
{
    final TextView timeView = (TextView) findViewById(R.id.time_view);
    final Handler handler = new Handler();
    handler.post(new Runnable() {
        @Override
        public void run() {
            int seconds = centiseconds / 100;
            int centisecs = centiseconds % 100;
            int hours = seconds / 3600;
            int minutes = (seconds % 3600) / 60;
            int secs = seconds % 60;

            String time = String.format("%d:%02d:%02d.%02d", hours, minutes, secs, centisecs);
            timeView.setText(time);
            if (isRunning) {
                centiseconds += 1;
            }
            handler.postDelayed(this, 10);
        }
    });
    }

}

Since postDelayed method's delay is in milliseconds, ten times of it would be 1 centiseconds. So I'm incrementing my centiseconds variable every 10ms.So far so good.

But when I test my app on my device, it seems the seconds are ticking slower than they should. Is is probable that the codes corresponding to division and modulo operations cause so much lag that hinder the increment and reduce the accuracy?

I've rewritten the app for 0.1 seconds(deciseconds) (by: centiseconds / 10 and % 10 and postDelayed(..., 100) ) and it seems it is ticking correctly.

P.S.
Is this the reason my 4.3 Jellybean's Stopwatch has 0.1 seconds accuracy?
What is the limit of precision in android for such app? ( Timely's has 0.01 seconds so I think it is at least 0.01 seconds)

Zeta.Investigator
  • 911
  • 2
  • 14
  • 31
  • 1
    first: such precision doesn't make any sens (maybe you need real time OS)... you can always "save" time on start and on stop take a timestamp between saved and "now" ... now about using postDelay with Handler from UI thread: it will always be inaccurate ... Handler is picking "jobs" from the queue 1 by 1 ... even if you postDelay the job with some given delay it will not started if somthing(like redrawing UI) is "working" ... – Selvin Aug 06 '15 at 12:05

1 Answers1

2

This is wrong approach as you cannot rely on system message queue as source of precise ticks as it does NOT guarantee any precision in delivery. postDelayed() queues your runnable to be delivered no sooner than now + delay but for precise delivery is not quaranteed and additional delays can happen for many reasons which in longer run would give you noticeable cumulative error in measurements.

You can however use postDelayed() to update your UI, but to know how much time passed you should use system clock methods, not own counters.

You also should fire your runnable at least twice per precision, i.e. if you want to update timer display once per minute, you should "tick" twice per minute so if there'd be any delay in message queue handling your UI shall still get at least one tick per second on time.

Marcin Orlowski
  • 72,056
  • 11
  • 123
  • 141