我想在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 post
和after post
,但绝不会看到inside post
。
我究竟做错了什么?
根本问题实际上与Kotlin无关。
问题是,如果视图当前附加到视图层次结构,则View.post()
仅在主线程上成功调度其工作。视图的最终附加不会发生在setContentView()
时。它发生在一段时间后。
如果当前未附加post()
的主题视图(如问题中所示),则View
为当前线程创建一个RunQueue
(存储为本地线程)并安排该RunQueue
上的工作。
因此,给定样本的问题如下。由于没有在主线程上调用View.post()
,它将为当前的非主线程创建一个新的RunQueue
,而不检查它是否由Looper
定向(就像主线程一样)。这意味着预定的Runnable
基本上进入了RunQueue
,直到Looper
开始才处理。在这里显示的情况下,Looper
永远不会启动,新线程终止,并且工作永远不会执行。
如果带有post
的新线程被延迟到视图被附加之后,例如,当在其上注册了点击时,post
可能能够在主线程上安排工作。但是这不是这里的情况,因为帖子发生1)在附加视图之前,2)在不同的非Looper
线程上立即终止。
我能够通过从post
启动线程来解决这个问题,即
view.post({
thread() {
info("before post")
view.post({ info("inside post") })
info("after post")
}
})
但我想明白为什么我需要那样做。
我建议你看看处理程序。它是一种在不同线程上执行操作时更新UI对象的更安全的方法。基本上你只需要将处理程序对象传递给你的线程以便更新Ui
更多信息在这里http://developer.android.com/intl/pt-br/reference/android/os/Handler.html