我正在编写一个使用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之后运行的时钟。我也在overDetachedFromWindow上覆盖了停止时钟,这会让问题消失,但这样做太过分了。如果用户接到电话,它也会停止时钟,赢得它,这不是我想要的。
你能建议如何最好地完成我想要的东西吗?有没有办法从活动中获取时钟?我曾想过在onDestroy中发出一些事件,并让ChessClock听取它,但我还不知道如何编写自定义事件和监听器。有没有更简单的方法?
答案 0 :(得分:0)
我不知道怎么在Kotlin中这样做,但在java中你可以设置Timer每X毫秒执行一次timertask然后在需要时取消它,调用mTimer.cancel() 您应该尝试使用它而不是mHandler.postDelayed(this,mInterval)
答案 1 :(得分:0)
我不明白所提出的建议如何解决我的问题,但我想出了一个kludge。
我将全局变量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)
}
}
不是一个很好的解决方案,但在我找出自定义事件之前必须这样做。据我所知,自定义事件和自定义事件监听器是唯一干净的方法。