Kotlin
class MainModel : BaseViewModel() {
// 持有定时任务的Job对象,用于后续取消任务
private var timerJob: Job? = null
// 定时任务结束的高阶函数回调(上层注册,ViewModel内部触发)
var onTimerFinish: (() -> Unit)? = null
/**
* 启动定时任务
* @param delaySeconds 延迟执行的秒数(N秒)
*/
fun startTimerTask(delaySeconds: Long) {
// 先取消已有任务,避免重复启动
cancelTimerTask()
// 基于viewModelScope启动协程,生命周期与ViewModel绑定
timerJob = viewModelScope.launch {
try {
// 核心:延迟N秒执行(单位:毫秒)
delay(delaySeconds * 1000)
// 定时任务正常结束,触发回调通知上层
onTimerFinish?.invoke()
} catch (e: Exception) {
// 协程被取消时会抛出CancellationException,此处捕获避免崩溃
// 硬件错误/手动取消时,任务终止,不触发结束回调
e.printStackTrace()
}
}
}
/**
* 取消定时任务(硬件错误/手动终止时调用)
*/
fun cancelTimerTask() {
// 取消Job并置空,确保任务完全终止
timerJob?.cancel()
timerJob = null
}
/**
* ViewModel销毁时自动调用,双重保障取消任务(防止内存泄漏)
*/
override fun onCleared() {
super.onCleared()
cancelTimerTask()
// 清空回调,避免上层页面已销毁仍持有引用
onTimerFinish = null
}
}
使用:
Kotlin
class TimerTaskActivity : AppCompatActivity() {
private lateinit var timerViewModel: TimerTaskViewModel
private lateinit var btnStart: Button
private lateinit var btnCancel: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_timer_task)
// 初始化ViewModel(ViewModelProvider确保生命周期独立于Activity)
timerViewModel = ViewModelProvider(this)[TimerTaskViewModel::class.java]
// 绑定控件
btnStart = findViewById(R.id.btn_start_timer)
btnCancel = findViewById(R.id.btn_cancel_timer)
// 1. 点击开始:执行5秒定时任务(可自定义delaySeconds)
btnStart.setOnClickListener {
Toast.makeText(this, "定时任务启动,5秒后结束", Toast.LENGTH_SHORT).show()
timerViewModel.startTimerTask(delaySeconds = 5)
}
// 2. 注册定时任务结束回调:执行后续业务逻辑
timerViewModel.onTimerFinish = {
runOnUiThread { // 确保回调在主线程执行(UI操作必须主线程)
Toast.makeText(this, "定时任务结束!开始执行后续逻辑", Toast.LENGTH_LONG).show()
// 此处写你的后续业务逻辑(如接口请求、UI更新、数据处理等)
doSubsequentLogic()
}
}
// 3. 硬件错误/手动取消:点击按钮终止任务(实际可在硬件错误回调中调用)
btnCancel.setOnClickListener {
timerViewModel.cancelTimerTask()
Toast.makeText(this, "定时任务已取消", Toast.LENGTH_SHORT).show()
}
}
/**
* 定时任务结束后的后续逻辑示例
*/
private fun doSubsequentLogic() {
// 示例:更新UI、请求网络、操作数据库等
btnStart.isEnabled = true
// ... 你的业务代码
}
/**
* 页面销毁时,ViewModel会自动调用onCleared()取消任务,无需额外处理
* 若有硬件错误检测逻辑,可在对应的回调中调用 timerViewModel.cancelTimerTask()
*/
// 示例:硬件错误检测回调(根据实际硬件SDK调整)
private fun onHardwareErrorDetected() {
timerViewModel.cancelTimerTask()
Toast.makeText(this, "检测到硬件错误,已取消定时任务", Toast.LENGTH_SHORT).show()
}
}