发布到UI线程

时间:2016-04-01 12:38:49

标签: android multithreading kotlin android-handler ui-thread

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

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

我做错了什么?

3 个答案:

答案 0 :(得分:5)

潜在的问题实际上与Kotlin无关。

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

如果当前未附加post()的主题视图(如问题中所示),View会为当前主题创建RunQueue(存储为本地线程)并安排RunQueue上的工作。

因此,给定样本的问题如下。由于未在主线程上调用View.post(),因此它将为当前的非主线程创建新的RunQueue,而不检查它是否由{{1}定向(作为主线程)。这意味着预定的Looper基本上会进入Runnable,直到RunQueue开始才会处理。在此处显示的情况下,Looper永远不会启动,新线程终止,并且永远不会执行工作。

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

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

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

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