安卓中短信验证码倒计时的几种方式
2017-12-21 15:17
393 查看
发送短信验证码后,一般在界面上都会有一个倒计时的显示.在安卓中,实现类似的倒计时有多种方式,当然背后的基本原理都是设定一个初始值,然后每过一定的间隔时间执行操作.
CountDownTimer内部也是用Handler实现的.形参是总记时时间和时间间隔.当倒计时任务开始后,在handleMessage方法中会不断调用sendMessageDelayed方法,相当于每隔一段时间后回调onTick方法,这里就可以做界面实时更新的逻辑.内部有一个millisLeft记录剩余的时间,<=0时会回调onFinish方法.此时最好调用一次cancel方法,内部的Handler会移除之前定义的消息.
但是发送通知的间隔时间并非直接等于传入的参数,而是会通过SystemClock.elapsedRealtime()方法计算得出.这个值得到的是手机本次开机后到当前的总时间.每次累计的时候会有几毫秒的误差,最终导致显示的时候某个时间值可能不是很准确.上面的日志显示了倒计时开始后的实时时间,预先定义的间隔为1000毫秒.
该方法的原理是开启了一个线程,并执行定时操作.因为TimerTask是Java中一个实现了Runnable接口的抽象类,配合Timer类可以完成一段时间或者重复性的任务.Timer类中的schedule方法将二者联系在一起,简单的说Timer负责记时,TimerTask负责执行具体的任务.这里我们定义了一个倒计时的初始值time=60(s),run方法每隔给定的时间间隔后执行一次.当倒计时结束后一定要手动调用cancel,否则后台任务会一直执行下去,造成资源的浪费.更新控件的操作要放在UI线程中操作.
这种方法的好处是时间值相对准确,并且应用场景不止于验证码倒计时.将定义的time类型修改为static,还可以实现倒计时在页面销毁后正常计时,再次创建页面后仍显示准确的值.
基本原理就是利用Handler在主线程和子线程之间进行通信.此处的时间间隔用的是线程休眠1000毫秒,基本和延迟发送消息一个意思.需要注意的是内部类会持有外部类的引用,因此Activity销毁后Handler中有耗时操作还持有其引用,就会造成内存泄露.因此需要将Handler声明为静态内部类,并且持有Activity的弱引用,这样可以操作类中声明的控件和变量,而不必将它们全部声明为静态的.
用安卓自带的CountDownTimer实现
这是最简洁的实现方式.安卓提供了一个CountDownTimer类用于倒计时功能.其使用方法在注释里面写的已经比较清楚了.记时开启后禁掉控件的点击事件,倒计时结束后再开启.防止重复点击导致多个任务运行.private void countDownTime() { //用安卓自带的CountDownTimer实现 CountDownTimer mTimer = new CountDownTimer(60 * 1000, 1000) { @Override public void onTick(long millisUntilFinished) { Log.i(TAG, "millisUntilFinished: " + millisUntilFinished); btn1.setText(millisUntilFinished / 1000 + "秒后重发"); } @Override public void onFinish() { btn1.setEnabled(true); btn1.setText("发送验证码"); cancel(); } }; mTimer.start(); btn1.setEnabled(false); }
CountDownTimer内部也是用Handler实现的.形参是总记时时间和时间间隔.当倒计时任务开始后,在handleMessage方法中会不断调用sendMessageDelayed方法,相当于每隔一段时间后回调onTick方法,这里就可以做界面实时更新的逻辑.内部有一个millisLeft记录剩余的时间,<=0时会回调onFinish方法.此时最好调用一次cancel方法,内部的Handler会移除之前定义的消息.
11-21 11:51:18.529 12704-12704/com.mercury.countdown I/Main2Activity: millisUntilFinished: 59999 11-21 11:51:19.530 12704-12704/com.mercury.countdown I/Main2Activity: millisUntilFinished: 58998 11-21 11:51:20.532 12704-12704/com.mercury.countdown I/Main2Activity: millisUntilFinished: 57996 11-21 11:51:21.534 12704-12704/com.mercury.countdown I/Main2Activity: millisUntilFinished: 56993 11-21 11:51:22.538 12704-12704/com.mercury.countdown I/Main2Activity: millisUntilFinished: 55990 11-21 11:51:23.540 12704-12704/com.mercury.countdown I/Main2Activity: millisUntilFinished: 54988 11-21 11:51:24.542 12704-12704/com.mercury.countdown I/Main2Activity: millisUntilFinished: 53986 11-21 11:51:25.544 12704-12704/com.mercury.countdown I/Main2Activity: millisUntilFinished: 52984 11-21 11:51:26.545 12704-12704/com.mercury.countdown I/Main2Activity: millisUntilFinished: 51982 11-21 11:51:27.548 12704-12704/com.mercury.countdown I/Main2Activity: millisUntilFinished: 50980
但是发送通知的间隔时间并非直接等于传入的参数,而是会通过SystemClock.elapsedRealtime()方法计算得出.这个值得到的是手机本次开机后到当前的总时间.每次累计的时候会有几毫秒的误差,最终导致显示的时候某个时间值可能不是很准确.上面的日志显示了倒计时开始后的实时时间,预先定义的间隔为1000毫秒.
用Java的TimerTask配合Timer实现(定时任务)
private void usingTimer() { //使用Java的Timer配合TimerTask(定时任务) time = 60; final Timer timer = new Timer(); mTimerTask=new TimerTask() { @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { if (time <= 0) { cancel(); btn2.setEnabled(true); btn2.setText("发送验证码"); } else { btn2.setEnabled(false); btn2.setText(time + "秒后重发"); } Log.i(TAG, "time: " + time); time--; } }); } }; timer.schedule(mTimerTask, 0, 1000); }
该方法的原理是开启了一个线程,并执行定时操作.因为TimerTask是Java中一个实现了Runnable接口的抽象类,配合Timer类可以完成一段时间或者重复性的任务.Timer类中的schedule方法将二者联系在一起,简单的说Timer负责记时,TimerTask负责执行具体的任务.这里我们定义了一个倒计时的初始值time=60(s),run方法每隔给定的时间间隔后执行一次.当倒计时结束后一定要手动调用cancel,否则后台任务会一直执行下去,造成资源的浪费.更新控件的操作要放在UI线程中操作.
这种方法的好处是时间值相对准确,并且应用场景不止于验证码倒计时.将定义的time类型修改为static,还可以实现倒计时在页面销毁后正常计时,再次创建页面后仍显示准确的值.
用Handler的方式实现
private static class MyHandler extends Handler { WeakReference<Main2Activity> mReference; private MyHandler(Main2Activity activity) { mReference = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) { Main2Activity main2Activity = mReference.get(); if (main2Activity.time > 0) { main2Activity.btn3.setText(main2Activity.time + "秒后重发"); main2Activity.btn3.setEnabled(false); } else { main2Activity.btn3.setText("发送验证码"); main2Activity.btn3.setEnabled(true); } } }
//触发倒计时的点击事件 private void useHandler() { final MyHandler handler = new MyHandler(this); time = 60; Thread thread=new Thread(new Runnable() { @Override public void run() { while (time >= 0) { time--; handler.sendEmptyMessage(0); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }); thread.start(); }
基本原理就是利用Handler在主线程和子线程之间进行通信.此处的时间间隔用的是线程休眠1000毫秒,基本和延迟发送消息一个意思.需要注意的是内部类会持有外部类的引用,因此Activity销毁后Handler中有耗时操作还持有其引用,就会造成内存泄露.因此需要将Handler声明为静态内部类,并且持有Activity的弱引用,这样可以操作类中声明的控件和变量,而不必将它们全部声明为静态的.
相关文章推荐
- Android短信验证码倒计时验证的2种常用方式
- WebService的几种验证方式
- 安卓多线程编程系列5:使用message的几种不同方式(不同的构造方法和使用方式)续
- 安卓开发请求服务器的两种方式GET与POST(另附验证码的倒计时)
- swift 3.0 短信验证码倒计时实现
- 短信接口发送验证码倒计时以及提交验证
- 安卓中发短信的几种方式总结和实现
- iOS 短信验证码倒计时按钮的实现
- asp.net中常用的几种身份验证方式
- WebService的几种验证方式
- ios短信验证码倒计时功能
- asp.net中常用的几种身份验证方式
- 安卓应用启动其他应用的几种方式
- 后台参数验证的几种方式
- 几种实现身份验证的方式
- 短信验证 倒计时60秒
- MVC全局用户验证的的几种方式
- 微信小程序点击发送短信验证(60秒倒计时)
- Swift实现iOS应用中短信验证码倒计时功能的实例分享
- jQuery短信验证倒计时功能实现方法详解