Kotlin:每秒调用一个函数

Ale*_*nos 6 android kotlin

我想为我的游戏创建一个简单的倒计时,当游戏开始时,我希望每秒调用一次此函数:

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


Nhấ*_*ang 7

问题: 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)