Android ViewModel定时任务

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()
    }
}
相关推荐
油丶酸萝卜别吃9 分钟前
utils.js 说明文档
开发语言·javascript·ecmascript
zyplayer-doc3 小时前
VuePress类静态文档站和动态知识库怎么选:两种技术路线的适用场景
javascript·人工智能·后端·安全·智能手机
leisoo80973 小时前
100GBA股股票数据怎么存ClickHouseRedisMySQLJSON完整对比
大数据·linux·服务器·开发语言·python
不会代码的小猴4 小时前
21. 泛型编程上
开发语言·c++·笔记·算法
一只旭宝4 小时前
细讲C加加【9】C++ std::function与std::bind详解|仿函数、绑定器、类成员绑定、占位符、成员偏移指针
开发语言·c++·算法
我就是妖怪6 小时前
KMP全栈开发:从Android到AI Agent的技术演进与实践
android·人工智能
coder!mq7 小时前
说几个常见的语法糖?
java·开发语言·算法
gugucoding7 小时前
38. 【Java】Stream API(下):高级操作与性能
java·开发语言
Lhan.zzZ7 小时前
在 Visual Studio 2022 中打造可扩展的动态链接库模块:从零搭建到原理解析
开发语言·c++·visual studio
心平气和量大福大7 小时前
android-实例-蒲公英-更新与安装-5-签名与生成APK
android·java·开发语言