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()
    }
}
相关推荐
Joy T5 小时前
Agent 确定性上下文设计:从 Prompt 参数注入到能力分层
java·开发语言·微服务·架构·prompt·agent context
半个落月9 小时前
LangSmith 全链路观测(下):用 Dataset 与 LLM Judge 量化评估 RA
javascript·langchain
专注仿真9 小时前
引擎扩展性与集成设计深度剖析:从 14 个扩展点到 DIS→HLA 演进之路
开发语言·算法·仿真引擎·推演引擎
Best-Wishes9 小时前
科来网络分析系统(技术交流版)使用说明书
开发语言·junit·php
半个落月9 小时前
LangSmith 全链路观测(上):用 LangGraph 与 Milvus 构建可追踪的 RAG 客服
javascript·langchain
代码不停10 小时前
自动化测试(java)
java·开发语言·selenium·自动化
半个落月10 小时前
LangChain.js Agent 中间件实战:生命周期、动态工具与文件权限
javascript·langchain
志尊宝11 小时前
Vue3 零基础每日笔记(082):文件上传实战——el-upload 校验、自定义上传、头像预览
前端·javascript·vue.js·笔记·#javascript·#vue.js
鬼手点金11 小时前
opencode-rules 插件
java·开发语言·前端·人工智能·chrome·git·github
爱上网的小舟12 小时前
星际战士2启动错误怎么办?5种游戏报错解决方法
开发语言·php