验证码计时器-CountDownTimer就可以了

最近两个月项目赶得紧,没有学习什么新技术,就是对基础进行了巩固。每个安卓项目中都少不了登录注册的模块,既然有注册,那么获取验证码的功能是少不了的(都是固定套路)。其实获取验证码实现倒数计时的这个功能很多人都做过,而且有好几种实现方式,比如(java自带的Timer,Thread+Handler,AlarmManager等);今天我就给大家送上android系统封装好的倒计时工具CountDownTimer,其实CountDownTimer内部也是通过Handler发延迟消息实现的;为了能适应项目的要求我对CountDownTimer进行了自己的二次封装。

下面就是我封装的工具类,有兴趣的可以拿去试试,具体的我都写了注释,这里我没有用泛型,一般的都是个Button,有可能为了扁平化会用TextView,这些都不是什么大问题。由于不同的项目的主题色调和字体颜色不同,所以我把这些可能改变的东西都放在了构造方法中,以便适应于不同的产品需求
验证码计时器-CountDownTimer就可以了_第1张图片

/**
 * Created by rongtao on 2016/11/19.
 * 乐视****项目
 * 倒计时
 */

public class CountDownUtils extends CountDownTimer {
    private Button mView;//倒计时按钮
    private Context mContext;
    private int mNormal_bg,mNormal_txt_color;

    /**
     *
     * @param context
     * @param millisInFuture 倒计时总时长 单位毫秒
     * @param countDownInterval 每次减少量(步长)单位毫秒
     * @param btnView  倒计时按钮
     * @param pressed_bg 按下时的按钮背景色
     * @param normal_bg 正常的背景色
     * @param pressed_txt_color 按下时的按钮文本颜色
     * @param normal_txt_color 正常的按钮文本颜色
     */
    public CountDownUtils(Context context, long millisInFuture, long countDownInterval, Button btnView, int pressed_bg, int normal_bg, int pressed_txt_color, int normal_txt_color) {
        super(millisInFuture, countDownInterval);
        this.mView = btnView;
        this.mContext = context;
        this.mNormal_bg=normal_bg;
        this.mNormal_txt_color=normal_txt_color;
        //在初始化的时候将按钮置灰,防止重复请求
        mView.setBackgroundResource(pressed_bg);
        setTextColor(pressed_txt_color);
        mView.setClickable(false);//避免重复点击
    }

    /**
     * 计时操作
     * @param millisUntilFinished 计时时间的毫秒值
     */
    @Override
    public void onTick(long millisUntilFinished) {
        Log.d("onTick", millisUntilFinished + "");
        mView.setText(millisUntilFinished / 1000 + "秒后重新获取");
    }
    /**
     * 计时结束
     */
    @Override
    public void onFinish() {
        //计时结束后将按钮的状态复原
        mView.setText("获取验证码");
        mView.setClickable(true);
        mView.setBackgroundResource(mNormal_bg);
        setTextColor(mNormal_txt_color);
        this.cancel();
    }

    private void setTextColor(int font_color) {
          // ContextCompat.getColor(mContext,font_color); 可以用这个兼容方法,也可以自己手动判断
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
            mView.setTextColor(mContext.getColor(font_color));
        } else {
            mView.setTextColor(mContext.getResources().getColor(font_color));
        }
    }
}

具体用法,一般都是在点击按钮后向服务器发送请求,当服务器返回的响应码为200的时候开启倒计时

//在请求成功后做此操作
new CountDownUtils(mContext,
                          5 * 1000,
                          1000,
                          mBtnGetCode,
                          R.drawable.bg_btn_reqcode_gray,
                          R.drawable.bg_btn_reqcode,
                          R.color.font_black,
                          R.color.font_common_theme)
                          .start();

下面附上CountDownTimer的系统源码,有兴趣的自己看,也就100多行,主要就是start,cancel以及handleMessage中的同步代码块

public abstract class CountDownTimer {

    /**
     * Millis since epoch when alarm should stop.
     */
    private final long mMillisInFuture;

    /**
     * The interval in millis that the user receives callbacks
     */
    private final long mCountdownInterval;

    private long mStopTimeInFuture;

    /**
    * boolean representing if the timer was cancelled
    */
    private boolean mCancelled = false;

    /**
     * @param millisInFuture The number of millis in the future from the call
     *   to {@link #start()} until the countdown is done and {@link #onFinish()}
     *   is called.
     * @param countDownInterval The interval along the way to receive
     *   {@link #onTick(long)} callbacks.
     */
    public CountDownTimer(long millisInFuture, long countDownInterval) {
        mMillisInFuture = millisInFuture;
        mCountdownInterval = countDownInterval;
    }

    /**
     * Cancel the countdown.
     */
    public synchronized final void cancel() {
        mCancelled = true;
        mHandler.removeMessages(MSG);
    }

    /**
     * Start the countdown.
     */
    public synchronized final CountDownTimer start() {
        mCancelled = false;
        if (mMillisInFuture <= 0) {
            onFinish();
            return this;
        }
        mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
        mHandler.sendMessage(mHandler.obtainMessage(MSG));
        return this;
    }


    /**
     * Callback fired on regular interval.
     * @param millisUntilFinished The amount of time until finished.
     */
    public abstract void onTick(long millisUntilFinished);

    /**
     * Callback fired when the time is up.
     */
    public abstract void onFinish();


    private static final int MSG = 1;


    // handles counting down
    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            synchronized (CountDownTimer.this) {
                if (mCancelled) {
                    return;
                }

                final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();

                if (millisLeft <= 0) {
                    onFinish();
                } else if (millisLeft < mCountdownInterval) {
                    // no tick, just delay until done
                    sendMessageDelayed(obtainMessage(MSG), millisLeft);
                } else {
                    long lastTickStart = SystemClock.elapsedRealtime();
                    onTick(millisLeft);

                    // take into account user's onTick taking time to execute
                    long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();

                    // special case: user's onTick took more than interval to
                    // complete, skip to next interval
                    while (delay < 0) delay += mCountdownInterval;

                    sendMessageDelayed(obtainMessage(MSG), delay);
                }
            }
        }
    };
}

你可能感兴趣的:(android)