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

时间:2021-11-15 22:04:22

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

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

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

2、自定义倒计时按钮

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

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

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

private static class MyHandlerextends android.os.Handler{
    WeakReference<MainActivity> mActivity;

    publicMyHandler(MainActivity activity) {
        mActivity= newWeakReference<>(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 = newRunnable() {
        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