发布到UI线程

问题描述 投票:2回答:3

我想在onCreate中创建一个新线程,并使用post上的View与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

我究竟做错了什么?

android multithreading kotlin android-handler ui-thread
3个回答
5
投票

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

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

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

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

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


0
投票

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

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

但我想明白为什么我需要那样做。


0
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.