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()
    }
}
相关推荐
用户69371750013843 小时前
Google 正在“收紧侧加载”:陌生 APK 安装或需等待 24 小时
android·前端
用户69371750013843 小时前
Room 3.0:这次不是升级,是重来
android·前端·google
似水明俊德5 小时前
02-C#.Net-反射-面试题
开发语言·面试·职场和发展·c#·.net
Thera7775 小时前
C++ 高性能时间轮定时器:从单例设计到 Linux timerfd 深度优化
linux·开发语言·c++
炘爚6 小时前
C语言(文件操作)
c语言·开发语言
alexhilton6 小时前
Compose中的ContentScale:终极可视化指南
android·kotlin·android jetpack
阿蒙Amon6 小时前
C#常用类库-详解SerialPort
开发语言·c#
凸头6 小时前
CompletableFuture 与 Future 对比与实战示例
java·开发语言
wuqingshun3141597 小时前
线程安全需要保证几个基本特征
java·开发语言·jvm
Moksha2627 小时前
5G、VoNR基本概念
开发语言·5g·php