CountDownTimer 是什么
- 一个可以设置总时间,间隔时间,支持Tick回调和完成回调的实现
用在什么地方
-
商品详情页预售有倒计时处理
-
收银台有支付倒计时处理
-
首页二期也有倒计时处理
不是已经有实现了的么
-
是的
-
但是有些实现有问题,比如
CountDownTimerUtils
,使用了单例,会导致内存泄露问题 -
缺乏一个统一标准的实现
如何使用
View篇
// 设置倒计时
view.applyCountDownTimer(10 * DateUtils.SECOND_IN_MILLIS, 1000, object: CountDownTimerCallback() {
override fun onTick(millisUntilFinished: Long) {
super.onTick(millisUntilFinished)
smartLog {
"applyCountDownTimerForView millisUntilFinished=$millisUntilFinished"
}
}
override fun onFinish() {
super.onFinish()
smartLog {
"applyCountDownTimerForView onFinish"
}
}
})
//取消倒计时
addTestItem("主动取消View层级倒计时") {
viewCountDownButton.cancelCountDownTimer()
}
Fragment层级
//设置倒计时
private fun applyCountDownTimerForFragment() {
this.applyCountDownTimer(10 * 1000, 1000, object: CountDownTimerCallback() {
override fun onTick(millisUntilFinished: Long) {
super.onTick(millisUntilFinished)
smartLog {
"applyCountDownTimerForFragment millisUntilFinished=$millisUntilFinished"
}
}
override fun onFinish() {
super.onFinish()
smartLog {
"applyCountDownTimerForFragment onFinish"
}
}
})
}
//取消倒计时
addTestItem("主动取消Fragment层级倒计时") {
this.cancelCountDownTimer()
}
Activity层级
//设置倒计时
private fun applyCountDownTimerForActivity() {
this.activity.applyCountDownTimer(10 * 1000, 1000, object: CountDownTimerCallback() {
override fun onTick(millisUntilFinished: Long) {
super.onTick(millisUntilFinished)
smartLog {
"applyCountDownTimerForActivity millisUntilFinished=$millisUntilFinished"
}
}
override fun onFinish() {
super.onFinish()
smartLog {
"applyCountDownTimerForActivity onFinish"
}
}
})
}
//取消倒计时
addTestItem("主动取消Activity层级倒计时") {
this.activity.cancelCountDownTimer()
}
如果我不主动取消会怎么样
- 除去业务需求,不主动取消完全没有问题
自带生命周期管理的实现 View
fun View?.applyCountDownTimer(millisInFuture: Long?, countDownIntervalInMills: Long?,
timerCallback: CountDownTimerCallback?) {
this ?: return
CountDownTimerProvider.renewCountDownTimer(this, millisInFuture, countDownIntervalInMills,
timerCallback)?.start()
applyLifecycleForViewCountDownTimer(this)
}
//自带生命周期管理
private fun applyLifecycleForViewCountDownTimer(target: View) {
target.addOnAttachStateChangeListener(object: View.OnAttachStateChangeListener {
override fun onViewDetachedFromWindow(view: View?) {
smartLog {
"CountDownExt onViewDetachedFromWindow view=$view"
}
CountDownTimerProvider.cancelCountDownTimer(view)
view?.removeOnAttachStateChangeListener(this)
}
override fun onViewAttachedToWindow(view: View?) {
smartLog {
"CountDownExt onViewAttachedToWindow view=$view"
}
}
})
}
自带生命周期管理实现 Fragment
fun Fragment?.applyCountDownTimer(millisInFuture: Long?, countDownIntervalInMills: Long?,
timerCallback: CountDownTimerCallback?) {
this ?: return
CountDownTimerProvider.renewCountDownTimer(this, millisInFuture, countDownIntervalInMills, timerCallback)
?.start()
this.doOnDestroy {
CountDownTimerProvider.cancelCountDownTimer(this)
}
}
fun Fragment?.doOnDestroy(runnable: FragmentToUnit? = null) {
this ?: return
runnable ?: return
this.fragmentManager?.registerFragmentLifecycleCallbacks(object: FragmentManager.FragmentLifecycleCallbacks() {
override fun onFragmentDestroyed(fm: FragmentManager, f: Fragment) {
super.onFragmentDestroyed(fm, f)
if (f == this@doOnDestroy) {
runnable.invoke(f)
fm.unregisterFragmentLifecycleCallbacks(this)
}
}
}, false)
}
自带生命周期实现 Activity
fun Activity?.applyCountDownTimer(millisInFuture: Long?, countDownIntervalInMills: Long?,
timerCallback: CountDownTimerCallback?) {
this ?: return
CountDownTimerProvider.renewCountDownTimzujianer(this, millisInFuture, countDownIntervalInMills, timerCallback)
?.start()
this.onDestroy {
CountDownTimerProvider.cancelCountDownTimer(this)
}
}
fun Activity.onDestroy(runnable: (Activity) -> Unit) {
observeCallback(object : ActivityLifecycleCallbacksImpl() {
override fun onActivityDestroyed(activity: Activity) {
super.onActivityDestroyed(activity)
if (this@onDestroy == activity) {
runnable(activity)
}
}
})
}
CountDownTimerProvider 是什么
- 一个CountDownTimer的集合体现
package com.secoo.commonsdk.ktx.secoo.countdown
import android.os.CountDownTimer
import com.secoo.commonsdk.ktx.smartLog
import java.util.*
object CountDownTimerProvider {
private val timerMap = WeakHashMap<Any, CountDownTimer>()
fun getCountDownTimer(key: Any?, millisInFuture: Long?, countDownIntervalInMills: Long?,
timerCallback: CountDownTimerCallback?): CountDownTimer? {
if (key == null || millisInFuture == null || countDownIntervalInMills == null
|| timerCallback == null) {
return null
}
return timerMap[key] ?: createCountDownTimer(millisInFuture, countDownIntervalInMills,
timerCallback).also {
timerMap[key] = it
}
}
fun renewCountDownTimer(key: Any?, millisInFuture: Long?, countDownIntervalInMills: Long?,
timerCallback: CountDownTimerCallback?): CountDownTimer? {
cancelCountDownTimer(key)
return getCountDownTimer(key, millisInFuture, countDownIntervalInMills, timerCallback)
}
private fun createCountDownTimer(millisInFuture: Long, countDownIntervalInMills: Long,
timerCallback: CountDownTimerCallback): CountDownTimer {
return object : CountDownTimer(millisInFuture, countDownIntervalInMills) {
override fun onFinish() {
timerCallback.onFinish()
}
override fun onTick(millisUntilFinished: Long) {
timerCallback.onTick(millisUntilFinished)
}
}
}
fun cancelCountDownTimer(key: Any?) {
smartLog {
"cancelCountDownTimer by key=$key"
}
key ?: return
timerMap[key]?.cancel()
timerMap.remove(key)
}
}