Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

preface

In actual projects, we often meet the requirement of countdown, for example, we need to limit the user's access to verification code when logging in, and limit the binding of mailbox or third-party account to prevent unnecessary losses to the company.

Realize there are many ways of, such as a Handler, CountDownTimer, Timer, although the countdown sounds simple, but involves a lot of logic, I listed first

  1. The data decreases slowly over time, and the text changes when it reaches 0To resendOr other copywriting
  2. When the user clicks, the countdown begins, the font color changes to gray, and it is not clickable
  3. When the time countdown ends, the font color changes to normal color, and can be clicked.
  4. Global record countdown time, to prevent stupid users from messing around (although the server can operate, we also need to consider this situation on the client side)

Code

At first, I thought I would use SharedPrefences to save the prefences locally, but this logic was cumbersome, and although we encapsulated it, the logic could not be too long, so we switched to the singleton mode

public class TimeCount {

    public static TimeCount getInstance() {
        if (timeCount == null) {
            synchronized (TimeCount.class) {
                if (timeCount == null) {
                    timeCount = new TimeCount();
                }
            }
        }
        return timeCount;
    }
}
Copy the code

Then we need to bind our control to this singleton class

@SuppressLint("StaticFieldLeak") private static volatile TimeCount timeCount = null; // page private Activity mActivity; // control private TextView messageEmailText; /** * @param activity * @param textView * @return binding control */ public TimeCount bindTextView(activity activity, TextView textView) { mActivity = activity; messageEmailText = textView; return this; }Copy the code

This time we chose to use CountDownTimer for encapsulation. Let’s define the logic of the countdown first

public class Count extends CountDownTimer { public Count(long millisInFuture, long countDownInterval) { super(millisInFuture, countDownInterval); } @SuppressLint("SetTextI18n") @Override public void onTick(long millisUntilFinished) { if (messageEmailText ! = null && messageEmailText.getVisibility() == View.VISIBLE && mActivity ! = null && ! mActivity.isFinishing()) { messageEmailText.setEnabled(false); Messageemailtext.settext ("(" + ^ ^ ^ ^ ^ ^) "); messageemailtext.settext ("(" + ^ ^ ^ ^ ^) "); } } @Override public void onFinish() { if (messageEmailText ! = null && messageEmailText.getVisibility() == View.VISIBLE && mActivity ! = null && ! Mactive.isfinishing ()) {messageEmailText.settext (" resend "); messageEmailText.setEnabled(true); } emailCount = null; cancel(); }}Copy the code

I’m not going to explain CountDownTimer, you can go to Baidu if you need it, but for every step that you set, it’s going to call onTick, and when it’s done it’s going to call onFinish.

  1. constructionalsuperThe first parameter is the total time in milliseconds; The second parameter is the step of time.
  2. messageEmailTextIs in thebindTextViewTextView, which checks whether it is visible or not.mActivityIt is also ourbindTextviewThe argument passed, which checks if it is not null, is closed. To prevent some low-level exception errors.
  3. onTickIn thesetEnabledTextView must be unclickable in the countdown.
  4. onTickParameter for the callback inmillisUntilFinishedIt’s the remaining time, which is just milliseconds, so we’re going to do it very simply.
  5. onFinishThere is no explanation for the truth,cancelCancel the countdown,setEnabledSo I can click,emailCount = null;We’ll talk about that later why

After the countdown logic and classes are handled, let’s write a method to start

Timing starts / * * * * * @ param millisInFuture * / public void startCountTimer (long millisInFuture) {/ / the countdown, if use the singleton storage time (emailCount == null) { emailCount = new Count(millisInFuture, 1000); } // start the countdown emailcount.start (); if (messageEmailText ! = null) { messageEmailText.setEnabled(true); messageEmailText.setTextColor(ContextCompat.getColor(mActivity, R.color.gray)); }}Copy the code

EmailCount = null; It echoes.

Okay, let’s use it

TimeCount.getInstance().bindTextView(this,mTv)
        .startCountTimer(10000);
Copy the code