我想为我的游戏创建一个简单的倒计时,当游戏开始时,我希望每秒调用一次此函数:
fun minusOneSecond(){
if secondsLeft > 0{
secondsLeft -= 1
seconds_thegame.text = secondsLeft.toString()
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试了这个:
var secondsLeft = 15
timer.scheduleAtFixedRate(
object : TimerTask() {
override fun run() {
minusOneSecond()
}
},0, 1000
) // 1000 Millisecond = 1 second
Run Code Online (Sandbox Code Playgroud)
但不幸的是,该应用程序停止了,第二次调用run函数
3周前,我才刚开始进行android开发和Kotlin,到目前为止,我对它的了解最多。
通过Xcode的快速操作,我使用了这一行,我认为类似的方法也可以在Kotlin中使用
setTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(minusOneSecond), userInfo: nil, repeats: true)
Run Code Online (Sandbox Code Playgroud)
gme*_*tax 13
我正在使用此代码每分钟更新一个时钟
fixedRateTimer("timer", false, 0L, 60 * 1000) {
this@FullscreenActivity.runOnUiThread {
tvTime.text = SimpleDateFormat("dd MMM - HH:mm", Locale.US).format(Date())
}
}
Run Code Online (Sandbox Code Playgroud)
所以你必须用参数1000而不是60*1000
小智 10
val timer = object: CountDownTimer(10000, 1000) {
override fun onTick(millisUntilFinished: Long) {
// do something
}
override fun onFinish() {
// do something
}
}
timer.start()
Run Code Online (Sandbox Code Playgroud)
您还可以使用 CountDownTimer 来实现此目的。由于这需要两个参数(总时间和间隔时间),
此外它还提供了一个完成方法来在总时间完成时执行任何任务。
小智 9
请用
inline fun Timer.schedule(
time: Date,
period: Long,
crossinline action: TimerTask.() -> Unit
): TimerTask
Run Code Online (Sandbox Code Playgroud)
参考: https: //kotlinlang.org/api/latest/jvm/stdlib/kotlin.concurrent/java.util.-timer/schedule.html
问题: Timer类使用带有队列的后台线程来按顺序排队并执行所有任务。从您的代码中,因为您更新了UI(更改minusOneSecond函数中的TextView内容)。这就是为什么应用程序引发以下异常并使您的应用程序崩溃的原因。
android.view.ViewRootImpl $ CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触摸其视图。
解决方案:有很多方法可以完成任务,但是我更喜欢使用Handler类中的post()和postDelayed()方法。因为它简单易懂。
val mainHandler = Handler(Looper.getMainLooper())
mainHandler.post(object : Runnable {
override fun run() {
minusOneSecond()
mainHandler.postDelayed(this, 1000)
}
})
Run Code Online (Sandbox Code Playgroud)
更新:来自作者的评论,有关如何从Handler暂停/恢复任务。这是一个例子。
class MainActivityKt : AppCompatActivity() {
lateinit var mainHandler: Handler
private val updateTextTask = object : Runnable {
override fun run() {
minusOneSecond()
mainHandler.postDelayed(this, 1000)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Your logic code
...
mainHandler = Handler(Looper.getMainLooper())
}
override fun onPause() {
super.onPause()
mainHandler.removeCallbacks(updateTextTask)
}
override fun onResume() {
super.onResume()
mainHandler.post(updateTextTask)
}
fun minusOneSecond() {
if secondsLeft > 0 {
secondsLeft -= 1
seconds_thegame.text = secondsLeft.toString()
}
}
}
Run Code Online (Sandbox Code Playgroud)