The content published by this account is first published on the public account: Chengxiang Moying (ID:cxmyDev), welcome to pay attention to obtain cutting-edge technology articles.

One, foreword

The need to update your UI every second, like a countdown, is fairly common. The most common scenario is the logic of captchas sending timeout retries, which requires a countdown logic to modify the UI every second to make the countdown user aware.

So the logic of the countdown, how to do the best?

A countdown, at least there are two requirements: accurate, stable.

Accurate means that a 2-minute countdown should be executed in 2 minutes, and stable means that every time you synchronize your UI updates, it’s about 1s apart.

Second, implementation ideas

1. Delay notification of UI updates for 1s each time

A countdown is essentially a fixed time interval for a fixed task, and the simplest way to do this is with handler.postdelayed ().

So let’s write a class called CountdownUtils, and let’s look at its structure.

As you can see, it’s based on a Handler to do the delay. This logic is very simple, directly on the code.

It’s also very simple to use, passing in two minutes.

new CountdownUtils(120).start()
Copy the code

If I look at the Log output,

From the Log, it does complete a countdown, second by second up to zero, but in order to see if it’s accurate, there is an interval record of the complete time of the countdown, see the problem? a120sThe countdown was executed124sThe left and right sides.

The problem is that handler.postdelayed () is not the exact time specified for the delay, but it really depends on the scheduling of the thread. The problem of total time difference cannot be solved by changing the Timer.

This problem, in some captcha countdown scenarios, there is no reference event point, each countdown, the error of tens of milliseconds, basically is not perceived by the user. However, in some cases, such as the countdown of video playback, such a reference case, a countdown of a few minutes, error of a few seconds, is very obvious Bug.

This is unstable, so, how to do the countdown steady?

2. Use CountDownTimer

To implement a countdown, Android actually provides the corresponding support class, that is CounDownTimer, it is in the Android. OS package, can fully realize a countdown logic.

Let’s see how it works first.

The CountDownTimer is very simple to use, listening for the countdown in onTick() and calling onFinish() when it is finished.

Let’s go ahead and see what the Log output is.

The total time, within milliseconds, looks a lot better than what we did on our own.

The onTick() callback parameter is a number in milliseconds. This value is incorrect, but it does not matter. Just round it to get the correct number of seconds.

For example, 2830 is 3s, and 1828 is 2s.

But if you look at it a little bit more closely, if you do the countdown in this way, you’ll notice that instead of getting 1s, you’ll get 3s-2s-finish, and that’s a problem that can be reflected in the Log.

CountDownTimer’s source code is a bit of a Bug, but how does it keep the total time accurate?

As you can see from the structure of the CountDownTimer, it is actually a delay using mHandler, moving on to the implementation code of the most important Handler.

In handleMessage (), with the help of a SystemClock elapsedRealtime (), is a system that it actually get started, now an absolute time, include system hibernation interval.

However, that’s not the point. The point is that the CountDownTimer uses this time to calculate a difference with respect to the 1s interval each time, that is, it corrects the error each time to make sure that the final total time error is milliseconds (which is essentially the error of the last postDelayed()).

Now that we’ve found the key to keeping CountDownTimer accurate, we can rewrite the code in the first Demo to solve the problem of no 1s state.

3. Dynamically calculate delay value

There’s nothing to say, just calculate the interval, and then subtract the extra milliseconds from the next 1s to correct for the interval.

Now that we’ve done that, let’s look at the Log output.

As you can see, the interval is dynamically adjusted every time, the status is updated every second, and the total duration is within milliseconds, which basically solves the countdown problem perfectly.

Third, summary

A countdown simply with handler.postdelayed () is not guaranteed to be accurate or stable. Details determine success or failure, and a countdown can be extreme.

The content published by this account is first published on the public account: Chengxiang Moying (ID:cxmyDev), welcome to pay attention to obtain cutting-edge technology articles.