发布到 UI 个话题

Posting to UI thread

我想在 onCreate 中创建一个新线程并使用 View 上的 post 与 UI 线程通信。但是,posted 语句似乎从来都不是 运行。这是一个小例子:

import android.app.Activity
import android.os.Bundle
import android.widget.TextView    
import kotlin.concurrent.*
import org.jetbrains.anko.*

class MainActivity: Activity(), AnkoLogger {
  protected override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    val view = TextView(this)
    setContentView(view)

    thread() {
      info("before post")
      view.post({ info("inside post") })
      info("after post")
    }
  }
}

查看日志,我只能看到before postafter post,但看不到inside post

我做错了什么?

我能够通过从 post 启动线程本身来解决这个问题,即

view.post({
  thread() {
    info("before post")
    view.post({ info("inside post") })
    info("after post")
  }
})

但我想了解为什么我需要这样做。

我建议您看看 Handlers。在不同的线程上执行操作时,它是一种更安全的更新 UI 对象的方法。基本上你只需要将处理程序对象传递给你的线程以更新 Ui

这里有更多信息 http://developer.android.com/intl/pt-br/reference/android/os/Handler.html

根本问题实际上与 Kotlin 无关。

问题在于,如果视图 当前 附加到视图层次结构,则 View.post() 仅在主线程上成功安排其工作。视图的最终附加不会在 setContentView() 时发生。它发生在一段时间后。

如果 post() 的主题视图当前未附加(如问题中所示的情况),View 会为当前创建一个 RunQueue thread(存储为本地线程)并安排 RunQueue.

上的工作

因此,给定样本的问题如下。由于 View.post() 没有在主线程上调用,它将为当前的非主线程创建一个新的 RunQueue,而不检查它是否被 Looper 引导(就像主线程)。这意味着计划的 Runnable 实质上进入 RunQueue,直到 Looper 开始才处理。在此处显示的情况下,Looper 从未启动,新线程终止,并且工作从未执行。

如果带有 post 的新线程被延迟到附加视图之后,例如,当在其上注册点击时,post 可能会安排工作主线程。但这里的情况并非如此,因为 post 发生在 1) 附加视图之前,以及 2) 在立即终止的不同非 Looper 线程上。