Android验证码倒计时实现方式总结
几乎所有的APP里面都有验证码倒计时按钮,自己在项目中也尝试,简单总结为以下三种:
1、使用线程和Handler的方式,定时刷新倒计时数字,这种方式容易导致内存泄露,所以一般都使用弱引用,控制数字的刷新。
2、自定义倒计时按钮
3、使用Android提供的CountDownTimer结合TextView实现倒计时功能
方式一是我刚开始做android的时候,因为那个时候android只学了个基础,学会了使用线程结合Handler的方式更新视图,具体实现如下:
private static class MyHandler extends android.os.Handler{
WeakReference
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