You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中Timer/TimerTask动态修改周期崩溃问题求助

问题描述

我是来自奥地利的Alois,3天前刚开始用Kotlin开发安卓应用,仅了解15年前学习的vb.net。正在开发一款儿子构思的小游戏:界面底部有SPEED、UPGRADE、INCOME三个按钮,顶部中间是TextView(mytxt),中间是ImageView。想用Timer/TimerTask实现初始1秒周期的自动加钱功能,点击SPEED按钮希望将周期每次减少100ms(最低100ms),但点击该按钮后程序无报错直接崩溃,附上代码请求修改解决。

崩溃原因
  • TimerTask重复调度问题:TimerTask被cancel()后就处于终止状态,无法再次调用timer.schedule()重新调度,这是崩溃的核心原因。
  • 变量作用域冲突:在onCreate中重新声明了var timerTask,覆盖了类成员变量private lateinit var timerTask,导致后续操作的对象和初始调度的对象不一致。
  • ImageView设置错误:使用setTag()并没有实际更换图片,应该用setImageResource()。
  • 逻辑冗余:money变量未被使用,自动加钱逻辑未关联income变量。
修改后的完整代码
package com.example.uyc_android
import android.annotation.SuppressLint
import android.os.Build
import android.os.Bundle
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import java.util.Timer
import java.util.TimerTask

class MainActivity : AppCompatActivity() {
    private lateinit var timer: Timer
    private var timerTask: TimerTask? = null
    private var money = 0
    private var timerPeriod: Long = 1000
    private var computerType = 1
    private var income = 1

    @SuppressLint("SetTextI18n")
    @RequiresApi(Build.VERSION_CODES.O)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val mytxt = findViewById<TextView>(R.id.txtMoney)
        val btnSpeed = findViewById<Button>(R.id.btnSpeed)
        val btnUpgrade = findViewById<Button>(R.id.btnUpgrade)
        val btnIncome = findViewById<Button>(R.id.btnIncome)
        val bild = findViewById<ImageView>(R.id.imagePC)

        timer = Timer()
        startTimer(mytxt)

        btnSpeed.setOnClickListener {
            timerPeriod -= 100L
            if (timerPeriod <= 100L) {
                timerPeriod = 100L
            }
            restartTimer(mytxt)
            btnSpeed.text = "SPEED ${timerPeriod}"
        }

        btnUpgrade.setOnClickListener {
            computerType++
            if (computerType >= 3) {
                computerType = 3
            }
            when(computerType) {
                1 -> bild.setImageResource(R.drawable.pc1)
                2 -> bild.setImageResource(R.drawable.pc2)
                3 -> bild.setImageResource(R.drawable.pc3)
            }
            btnUpgrade.text = "UPGRADE ${computerType}"
        }

        btnIncome.setOnClickListener {
            income++
            btnIncome.text = "INCOME ${income}"
        }
    }

    private fun startTimer(textView: TextView) {
        timerTask = object : TimerTask() {
            override fun run() {
                money += income
                runOnUiThread {
                    textView.text = money.toString()
                }
            }
        }
        timer.schedule(timerTask, 0, timerPeriod)
    }

    private fun restartTimer(textView: TextView) {
        timerTask?.cancel()
        startTimer(textView)
    }

    override fun onDestroy() {
        super.onDestroy()
        timerTask?.cancel()
        timer.cancel()
    }
}
修改说明
  • 每次调整周期时,先取消旧的TimerTask,再创建新任务重新调度,避免使用已终止的任务。
  • 将全局变量改为类成员变量,消除作用域冲突,减少全局命名空间污染。
  • 把setTag()替换为setImageResource(),实现ImageView的图片切换。
  • 完善加钱逻辑,让money关联income变量,点击INCOME按钮后加钱速度会提升。
  • 在onDestroy()中取消定时器,避免页面销毁后后台任务持续运行导致内存泄漏。

内容的提问来源于stack exchange,提问作者ortech

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 07:11:32