java - kotlin协程可以像java Timer一样使用吗?

标签 java android kotlin kotlin-coroutines

我想知道是否可以使用 kotlin 协程作为计时器,以便从代码中删除最大的 Java 引用。基本上我做了一个例子,我使用类 Timer 来处理计时器显示(毫秒精度)。看(注意 java 导入):

import javax.swing.*
import java.awt.FlowLayout
import java.util.*
import java.util.Timer

class Screen : JFrame() {

  private var label = JLabel("--")
  private var timer: Timer? = null

  init {
    setSize(600, 200)
    defaultCloseOperation = 3
    layout = FlowLayout()
    val bt = JButton("toggle timer")
    bt.addActionListener {
      if (timer == null) {
        val start = System.currentTimeMillis()
        timer = Timer()
        timer!!.scheduleAtFixedRate(object : TimerTask() {
          override fun run() {
            label.text = "elapsed milliseconds: ${System.currentTimeMillis() - start}"
          }
        }, 0, 1)
      } else {
        timer!!.cancel()
        timer = null
      }
    }

    add(label)
    add(bt)
    setLocationRelativeTo(null)
    isVisible = true
  }
}

fun main() {
  Screen()
}

我还尝试用一些协程代码替换经典的 Timer 并得到了这个:

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.awt.FlowLayout
import javax.swing.JButton
import javax.swing.JFrame
import javax.swing.JLabel

fun create(someCallback: () -> Unit) = CoroutineScope(Job()).launch {
  while (true) {
    someCallback()
    delay(1L)
  }
}

class Screen : JFrame() {

  var label = JLabel("--")
  var localJob: Job? = null

  init {
    setSize(600, 200)
    layout = FlowLayout()
    val bt = JButton("toggle timer")
    bt.addActionListener {
      if (localJob == null) {
        val start = System.currentTimeMillis()
        localJob = create { label.text = "elapsed milliseconds: ${System.currentTimeMillis() - start}" }
      } else {
        localJob!!.cancel()
        localJob = null
      }
    }

    add(label)
    add(bt)
    setLocationRelativeTo(null)
    isVisible = true
  }
}

fun main() {
  Screen()
}

我认为这两个代码基本上显示了实现之间的差异。不管怎样,我的问题是,与 Timer 类相比,我是否可以在性能方面简单地做到这一点。另外,如果有更好的方法来完成此行为而不是使用协程,请随时提出建议!

最佳答案

使用flow ,注意下面第一个启动 block

import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch

val clicks = MutableStateFlow(false)

suspend fun main(args: Array<String>) {
    coroutineScope {
        launch {
            clicks.withIndex().collectLatest { (idx, value) ->
                if (value) {
                    while (true) {
                        delay(1)
                        println("$idx label.text = ${System.currentTimeMillis()}")
                    }
                }
            }
        }
        launch {
            clicks.value = true
            delay(20)
            clicks.value = false
            delay(20)
            clicks.value = true
            delay(20)
            clicks.value = false
            delay(20)
            clicks.value = true
            delay(20)
            clicks.value = false
            delay(20)
            clicks.value = true
            delay(20)
            clicks.value = false
            delay(20)
        }
    }
}


我对swing不太了解,当按钮被点击时,切换值并将其设置为点击,现在一些解释

当事件发生时,collectLatest首先取消collectLatest中最后启动的协程,然后启动一个具有当前值的新协程,因此每次单击时,都会启动之前启动的协程while(true) 被取消,所以你不必处理取消事件,我认为这是最适合你的情况的解决方案

关于java - kotlin协程可以像java Timer一样使用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68969379/

相关文章:

java - 在JAVA字体颜色中使用HTML Color代码

具有等效负数和正数模式的 Java NumberFormat

java - 限制Java中的最大字符输出?

java - 在 fragment Android java中初始化ViewModel

Android Fragment 返回堆栈

android - Android 设备上的并发声音

java - 单个实体的多对多关系 - Hibernate

Android Kotlin Mvp 类委托(delegate)

Kotlin:抽象父类(super class)可以有抽象构造函数吗?

java - Kotlin: java.lang.UnsupportedOperationException 在 MutableList 添加元素