在Android视图中检测后退按钮

我正在写一个使用ChessClock类的游戏应用程序。 两名球员中的每一个都有一个时钟。 时钟每十分之一秒发送一个消息流,如果运行,则减少剩余的时间。 当时间到时时钟调用父视图组中的一个方法停止时钟,并设置一个标志,导致进一步的触摸事件被忽略,使用户不能再移动件。 我正在写kotlin,但是我认为这对java程序员也是清楚的:

class ChessClock : TextView { constructor(context: Context) : super(context) constructor(context:Context, p:String) : this(context) { player = p } var player = "" val RUNNING = 0 val PAUSED = 1 val IDLE = 2 val EXPIRED = 3 val mInterval = 100L var mTime = 0L // in milliseconds var mState = IDLE val mHandler = Handler() val mUpdateTimeTask = object : Runnable { override fun run() { if (mState == RUNNING) showTime() mHandler.postDelayed(this, mInterval) } } // override fun onDetachedFromWindow() { // super.onDetachedFromWindow() // stop() // } fun setTime(minutes:Long) { mTime = 1000*60*minutes // minutes to milliseconds mState = IDLE setTextColor(getResources().getColor(R.color.colorIdle)) showTime() mUpdateTimeTask.run() } fun pause() { mState = PAUSED setTextColor(getResources().getColor(R.color.colorPaused)) } fun start() { mState = RUNNING setTextColor(getResources().getColor(R.color.colorRunning)) } fun expire() { mState = EXPIRED setTextColor(getResources().getColor(R.color.colorExpired)) model.timeout(player) val aboyne = parent as AboyneView aboyne.gameOver(false) } fun toggle() { if (mState == PAUSED) start() else if (mState == RUNNING) pause() } fun stop() { mHandler.removeCallbacks(mUpdateTimeTask) } fun showTime() { val tenths = (mTime % 1000) / 100 var seconds = mTime / 1000 val minutes = seconds % 3600 / 60 seconds %= 60 if (minutes >= 1) setText(String.format("%02d:%02d",minutes, seconds)) else setText(String.format("%01d:%02d:%01d",minutes, seconds, tenths)) if (mState != RUNNING) return if (mTime > 0) mTime -= mInterval else expire() } } 

这工作正常,但如果用户按下后退按钮,然后开始一个新的游戏,时钟显然继续运行,即使活动的onDestroy方法已被调用。 然后,当运行时间到期时,即使新时钟仍在运行,新游戏也将被冻结。

我是新来的android,我不明白这是怎么来的。 我以为活动时钟就会被毁掉。 我已经测试了关于日志消息发生情况的想法,并确认了在调用onDestroy之后运行的时钟。 我也覆盖了DachachedFromWindow停止时钟,这使问题消失,但这是矫枉过正。 如果用户打电话,它也会停下来,不是吗,这不是我想要的。

你能建议如何最好地完成我想要的吗? 有没有办法从那里的活动访问时钟? 我想在onDestroy中发射一些事件,并让ChessClock监听它,但我不知道如何编写自定义事件和监听器。 有一个更简单的方法吗?

我不知道如何在Kotlin中做到这一点,但在Java中你可以设置计时器每X毫秒执行timertask,然后取消它,如果需要,调用mTimer.cancel()你应该尝试使用它,而不是mHandler.postDelayed(这, mInterval)

这里是如何做到这一点: 如何在Kotlin延迟后调用函数?

我不明白这些建议如何解决我的问题,但我想出了一个杂凑。

我做了一个全局变量BACK_BUTTON初始化为false 。 在活动中,我重写onDestroy以将BACK_BUTTON设置为true 。 然后我修改了ChessClock代码来检查BACK_BUTTON:

 val mUpdateTimeTask = object : Runnable { override fun run() { if (BACK_BUTTON) expire() else { if (mState == RUNNING) showTime() mHandler.postDelayed(this, mInterval) } } 

这不是一个很好的解决方案,但是直到我找出自定义事件之后才会这样做。 就我所见,自定义事件和自定义事件侦听器是唯一干净的方法。