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
相关产品推荐
相关产品推荐

