注册

Android超简单实现验证码倒计时,页面关闭不中断,杀掉进程也不中断

在日常开发中,获取验证码是一个常见的功能,通常验证码倒计时的实现思路都是使用CountDownTimer来实现,但是存在一个问题就是当页面关闭之后重新进入页面,倒计时是不会继续进行的,如果后端验证码接口做了时间限制,那么我们再次请求的时候就会报错,用户体验不好。 作为一名CV工程师,在一番百度之后,唯一找到的一个实现方案还需要花钱下载,哎。。。无奈只能自己想了。

实现思路

其实实现思路很简单,使用CountDownTimer进行倒计时,在开始倒计时的时候,把 当前时间+倒计时总时间 持久化存储,再次打开页面的时候判断一下当前时间是否在倒计时时间的范围内,如果在就继续倒计时。

效果如下

在这里插入图片描述

倒计时工具类

持久化存储我使用了腾讯的MMKV,当前你也可以使用SharedPreference 如果你使用的也是MMKV,别忘了在Application中初始化

package com.lzk.jetpacktest.code

import android.os.CountDownTimer
import com.tencent.mmkv.MMKV

/**
* @Author: LiaoZhongKai
* @Date: 2021/8/17 16:38
* @Description: 验证码倒计时工具类
*/
object CodeCountDownUtil {
private const val KEY_TIME = "TotalTimeMills"
private val mMkv: MMKV = MMKV.mmkvWithID("CodeCountDownUtil")
private var mTotalTimeMills = 0L
private var mListener: OnCountDownListener? = null

private val mCountDownTimer: CountDownTimer
get() {
return object : CountDownTimer(getCountTimeMills(),1000){
override fun onTick(millisUntilFinished: Long) {
mListener?.onTick(millisUntilFinished/1000)
}

override fun onFinish() {
mListener?.onFinish()
}

}
}

/**
* 开始倒计时
* [totalTimeMills] 倒计时时间毫秒值
*/
fun start(totalTimeMills: Long){
mTotalTimeMills = totalTimeMills+System.currentTimeMillis()
mMkv.encode(KEY_TIME, mTotalTimeMills)
mCountDownTimer.start()
}

/**
* 继续倒计时
*/
fun continueCount(){
mCountDownTimer.start()
}

/**
* 取消倒计时
*/
fun cancel(){
mCountDownTimer.cancel()
}

/**
* 获取当前的倒计时时间毫秒值
*/
fun getCountTimeMills(): Long{
mTotalTimeMills = mMkv.decodeLong(KEY_TIME)
return mTotalTimeMills - System.currentTimeMillis()
}

/**
* 当前时间是否在倒计时范围内
* @return true: 倒计时正在进行 false:倒计时未进行
*/
fun isCounting(): Boolean{
mTotalTimeMills = mMkv.decodeLong(KEY_TIME)
return System.currentTimeMillis() < mTotalTimeMills
}

/**
* 设置监听器
*/
fun setOnCountDownListener(listener: OnCountDownListener){
mListener = listener
}

interface OnCountDownListener{
/**
* 倒计时
* [seconds] 倒计时剩余时间,秒为单位
*/
fun onTick(seconds: Long)

/**
* 倒计时结束
*/
fun onFinish()
}
}

使用示例

package com.lzk.jetpacktest.code

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import com.lzk.jetpacktest.R
import com.lzk.jetpacktest.databinding.ActivityVerificationCodeBinding

/**
* @Author: LiaoZhongKai
* @Date: 2021/8/18 9:22
* @Description: 验证码页面
*/
class VerificationCodeActivity : AppCompatActivity() {

companion object{
//验证码倒计时总时间
//60秒
private const val COUNT_DOWN_TIME = 60*1000L
}

private lateinit var mBinding: ActivityVerificationCodeBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mBinding = DataBindingUtil.setContentView(this,R.layout.activity_verification_code)
initView()
initEvent()
}

//千万不要忘记在onDestroy中取消倒计时
//千万不要忘记在onDestroy中取消倒计时
//千万不要忘记在onDestroy中取消倒计时
override fun onDestroy() {
super.onDestroy()
CodeCountDownUtil.cancel()
}

private fun initView(){
//如果当前时间仍在倒计时范围内,则显示倒计时
if (CodeCountDownUtil.isCounting()){
CodeCountDownUtil.continueCount()
mBinding.btn.isEnabled = false
}else{//否则显示获取验证码
mBinding.btn.text = "获取验证码"
}
}

private fun initEvent(){
//设置监听器
CodeCountDownUtil.setOnCountDownListener(object : CodeCountDownUtil.OnCountDownListener{
override fun onTick(seconds: Long) {
mBinding.btn.text = "$seconds 秒后重新获取"
}

override fun onFinish() {
mBinding.btn.isEnabled = true
mBinding.btn.text = "获取验证码"
}

})

//获取验证码按钮
mBinding.btn.setOnClickListener {
//模拟验证码发送成功
Toast.makeText(this,"验证码已发送",Toast.LENGTH_SHORT).show()
//按照正常流程,以下代码应该在验证码发送成功之后再调用
//开始倒计时
CodeCountDownUtil.start(COUNT_DOWN_TIME)
mBinding.btn.isEnabled = false
}
}

}
xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">


<data>

</data>

<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".code.VerificationCodeActivity">


<Button
android:id="@+id/btn"
android:layout_width="150dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:text="获取验证码" />

</FrameLayout>
</layout>

0 个评论

要回复文章请先登录注册