Android验证码倒计时实现方式总结

       几乎所有的APP里面都有验证码倒计时按钮,自己在项目中也尝试,简单总结为以下三种:

1、使用线程和Handler的方式,定时刷新倒计时数字,这种方式容易导致内存泄露,所以一般都使用弱引用,控制数字的刷新。

2、自定义倒计时按钮

3、使用Android提供的CountDownTimer结合TextView实现倒计时功能

 

方式一是我刚开始做android的时候,因为那个时候android只学了个基础,学会了使用线程结合Handler的方式更新视图,具体实现如下:

private static class MyHandler extends android.os.Handler{
    WeakReference mActivity;

    publicMyHandler(MainActivity activity) {
        mActivity= new WeakReference<>(activity);
    }

    @Override
   
publicvoid handleMessage(Message msg) {
        // TODO Auto-generated method stub
       
final
MainActivity mf = mActivity.get();
        super.handleMessage(msg);
        switch(msg.what) {
            case 0:
                mf.sendOne.setText("重新发送");
                mf.count = 60;
                mf.sendOne.setEnabled(true);
                break;
            case 1:
                mf.sendOne.setEnabled(false);
                mf.sendOne.setText(mf.count+ "");
                break;
        }
    }

}


private void sendCode(){
    finalRunnable r = new Runnable() {
        publicvoid run() {
            runningOne= true;
            while(count > 0) {
                count = count- 1;
                handler.sendEmptyMessage(1);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                   
e.printStackTrace();
                }
            }
            runningOne= false;
            handler.sendEmptyMessage(0);
        }
    };
    Thread s = new Thread(r);
    s.start();
}

当然在使用这种方式的时候,我们还必须保证在倒计时期间,按钮是不能点击的,所以需要定义一个标志变量

if (runningOne) {} else {    sendCode();}

 

方式二:使用自定义按钮实现倒计时功能

public class CountButton extends Button implements View.OnClickListener {    /*     倒计时时长,默认计时时间     */    private long defaultTime = 60*1000;    private long time = defaultTime;    /*    开始执行计时的类,可以每间隔一秒执行任务     */    private Timer timer;    /*    执行的任务     */    private TimerTask task;    /*    默认文案     */    private String defaultText = "获取验证码";    /*    计时完成之后显示的文案     */    private String finishText = "重新发送";    /*    点击事件     */    private OnClickListener onClickListener;    public CountButton(Context context) {        super(context);        initView();    }    public CountButton(Context context, AttributeSet attrs) {        super(context, attrs);        initView();    }    public CountButton(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initView();    }    private void initView() {        if (!TextUtils.isEmpty(getText())) {            defaultText = getText().toString().trim();        }        this.setText(defaultText);        setOnClickListener(this);    }    /*    更新显示文案     */    private Handler handler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            CountButton.this.setText(time / 1000 + " ");            time -= 1000;            if (time < 0) {                CountButton.this.setEnabled(true);                CountButton.this.setText(finishText);                clearTimer();                time = defaultTime;            }        }    };    /*    清除倒计时     */    private void clearTimer() {        if (task != null) {            task.cancel();            task = null;        }        if (timer != null) {            timer.cancel();            timer = null;        }    }    /*    初始化时间     */    private void initTimer() {        timer = new Timer();        task = new TimerTask() {            @Override            public void run() {                handler.sendEmptyMessage(1);            }        };    }/*activity或者fragment消亡的时候清除倒计时 */    @Override    protected void onDetachedFromWindow() {        clearTimer();        super.onDetachedFromWindow();    }    public void setDefaultText(String defaultText) {        this.defaultText = defaultText;    }    public void setFinishText(String finishText) {        this.finishText = finishText;    }    public void setDefaultTime(long defaultTime) {        this.defaultTime = defaultTime;    }    @Override    public void onClick(View view) {        start();        if (onClickListener != null) {            onClickListener.onClick(view);        }    }    public void start() {        initTimer();        this.setText(time / 1000 + " ");        this.setEnabled(false);        timer.schedule(task, 0, 1000);    }    @Override    public void setOnClickListener(OnClickListener l) {        if (l instanceof CountButton) {            super.setOnClickListener(l);        } else {            this.onClickListener = l;        }    }}

为了实现方便,我没有使用attrs声明相关的属性,源码不多,需要使用的小伙伴可以直接在源码中修改

setDefaultTime(long defaultTime)方法设置倒计时总的计时时间,例如:sendTwo.setDefaultTime(60 * 1000);

setDefaultText(String defaultText)方法设置点击按钮之前显示的文案,例如:sendTwo.setDefaultText("发送验证码");
setFinishText(String finishText)方法设置倒计时完成之后显示的文案,例如:sendTwo.setFinishText("重新发送");
 
方法三:使用Android提供的CountDownTimer的onTick(long l) 和onFinish()方法控制计时中和结束后的相关操作,这种方式可以适用于很多倒计时的场景,个人觉得比较方便、适用。
private CountDownTimer downTimer = new CountDownTimer(60 * 1000, 1000) {    @Override    public void onTick(long l) {        runningThree = true;        sendThree.setText((l / 1000) + "");    }    @Override    public void onFinish() {        runningThree = false;        sendThree.setText("重新发送");    }};
然后使用downTimer.start()开始倒计时。
使用这种方式和第一种方式一样,我们也需要定义标志位来控制按钮的点击事件
if (runningThree) {} else {    downTimer.start();}
 
上面就是我在开发的过程中所接触过的倒计时方式,简单总结一下:
方式一,可以说是最复杂,也是最笨重的方式,这种方式容易引起内存泄露,及时使用了弱引用的方式,也避免不了内存泄露的可能。
方式二,比较简单,只需要设置好一些需要用到的字段和数值,就能够完成倒计时功能,方便、快捷。
方式三,简单,使用场合比较广泛,可以替代TimerTask,完成定时执行任务的操作,比较方便、适用。
 
源码我已经上传到CSDN上面,感兴趣的小伙伴可以下载看看,传送门开启:http://download.csdn.net/detail/zhimingshangyan/9670286

更多相关文章

  1. 箭头函数的基础使用
  2. NPM 和webpack 的基础使用
  3. Python list sort方法的具体使用
  4. 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程
  5. Android工程下build target,minSdkVersion,targetSdkVersion,maxSdk
  6. 18、ESC/POS指令集在android设备上使用实例(通过socket)
  7. Android应用启动后自动创建桌面快捷方式
  8. Android原生方式实现夜间模式
  9. 使用android中drawline函数无法绘制水平线的解决办法

随机推荐

  1. Android的碎片fragment和activity之前的
  2. android 中JNI开发中如何使用Socket
  3. 自定义 Android Preference——SpinnerPr
  4. Android中的UI更新
  5. Android 迁移到 Androidx
  6. 基于Platinum库的DLNA开发
  7. Android HTTPS认证之Volley封装
  8. react-natvie vscode真机调试[Android]
  9. android避免弹出软键盘遮盖listview
  10. 【Android 界面效果6】Android 控件之Ima