发布到UI线程
我想在onCreate
创建一个新线程,并使用View
上的post
与UI线程进行通信。 但是,编辑报表似乎并没有运行。 这是一个小例子:
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对象的更安全的方法。 基本上,你只需要传递处理程序对象到你的线程,以更新用户界面
更多信息在这里http://developer.android.com/intl/pt-br/reference/android/os/Handler.html