Android验证码倒计时实现方式总结
几乎所有的APP里面都有验证码倒计时按钮,自己在项目中也尝试,简单总结为以下三种:
1、使用线程和Handler的方式,定时刷新倒计时数字,这种方式容易导致内存泄露,所以一般都使用弱引用,控制数字的刷新。
2、自定义倒计时按钮
3、使用Android提供的CountDownTimer结合TextView实现倒计时功能
方式一是我刚开始做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