如何在 Kotlin 中使用 Thread.sleep()

Tec*_*rat 6 android sleep android-layout kotlin

这来自此处找到的 Codelab 的末尾部分:

调试简介 - 调试示例:访问不存在的值

这些都在 MainActivity.kt 文件中

这是我的 onCreate

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val helloTextView: TextView = findViewById(R.id.division_textview)
    helloTextView.text = "Hello, debugging!"

    division()
}
//...
Run Code Online (Sandbox Code Playgroud)

这是 Google 提供的除法函数,但有 2 个更改,我稍后会解释......

fun division() {
  val numerator = 60
  var denominator = 4
    repeat(4) {
     Thread.sleep(3000)
     findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")
     Log.v(TAG, "${numerator / denominator}")
     denominator--
    }
  }
Run Code Online (Sandbox Code Playgroud)

这些指令看起来他们期望sleep()接受秒,但 AS 表明它期望毫秒,所以我将他们的 3 更改为 3000。我添加了Log.v(TAG, "${numerator / denominator}")以查看发生了什么,因为它没有按预期进行。

这样做的目的是让模拟器创建一个正在更新的商的 gif。这在调试时应该很有帮助。

在完成之前,屏幕上不会显示任何内容,甚至连应用程序的名称也不会显示repeat()。正如预期的那样,日志每隔 3 秒发生一次。

为什么布局正在等待,以及如何使其在循环的每次迭代中更新?

cac*_*acs 5

老实说,根据他们提供的代码,我不知道 Codelab 在做什么。应用程序在完成之前不会渲染任何内容(不是布局,也不是​​对布局的任何更改)onCreate,并且在运行其所有代码(包括它调用的函数中的该块)onCreate之前不会完成。repeatdivision

division没有启动任何工作线程,所以Thread.sleep所做的只是阻塞主线程 - 它挂起应用程序。你是对的,sleep确实需要一个毫秒值,而不是秒 - 我感觉他们实际上并没有运行这段代码,它充满了其他错误和不一致之处,老实说很难弄清楚你应该做什么。改哪个Log.d电话?onCreate 中的那些?(我猜他们实际上是指Log.v打电话进来)division


以下是在 Kotlin 中使用线程的方法 - 您需要创建一个新线程(因此您离开了主线程,因此它实际上可以完成创建活动并运行 UI):

fun division() {
    // create a new thread (and start it immediately)
    thread(start=true) {
        repeat(4) { i ->
            Thread.sleep(3000L)
            // assuming you've done the ``findViewById`` and assigned it to a variable
            runOnUiThread { divisionTextView.text = "$i" }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

为了简洁起见,这只是用当前的重复次数 ( i) 进行更新,但重要的是:

  • 您正在创建一个新线程来完成工作(并睡觉)
  • 您正在使用(这是 Activity 上的一种方法)在主/UI 线程上runOnUiThread进行文本更新(相同的事情)。如果您尝试从另一个线程触摸 UI,它将崩溃

您可以做到这一点的另一种方法是post通过视图将可运行到 UI 线程,也可以使用TextView

divisionTextView.post { divisionTextView.text = "$i" }
Run Code Online (Sandbox Code Playgroud)

协程在这里会是一个更好的主意(您可以在主线程上运行它们而不会阻塞,因此您不必担心切换线程来更新 UI,或任何线程安全的东西),但这是执行线程的基础知识。真的不知道该 Codelab 中发生了什么。