如何从协程结果访问视图属性

How to acces view properties from coroutines result

我正在尝试使用协程向后端发出简单请求

    uiScope.launch {
        try {
             result = URL("https://httpbin.org/get").readText()
            text.text = result
        } catch (error: Error) {
            text.text = error.message
        } finally {
                log(this@MainActivity,result)

        }
    }

但是抛出了这个异常:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

如何解决?

您的 uiScope 设置不正确,显然它的调度程序不是 Dispatchers.Main。所以首先要修复的是 coroutineContext 属性 的实现,它应该是

override val coroutineContext = Dispatchers.Main + SupervisorJob()

修复该问题后,您的代码将在 UI 线程上进行阻塞调用。要在后台线程上进行阻塞调用,但仍将协程的其余部分保留在 UI 线程上,请编写

uiScope.launch {
    try {
         text.text = withContext(Dispatchers.IO) {
             URL("https://httpbin.org/get").readText()
         }
    } catch (e: Exception) {
        text.text = e.message
    } finally {
        log(this@MainActivity, result)
    }
}

我找到了解决方案。我无法从另一个线程访问 UI 组件,同时我无法在主线程上进行互联网请求。所以我应该选择其中之一。解决方案是使用 ViewModel 组件并更新它的 LiveDate 值,该值随后将更改 UI

    var viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
    viewModel.selected.observe(this, Observer{ users ->

        text.text = users
    })
    uiScope.launch {
            try {
                result = URL("http://jsonplaceholder.typicode.com/posts").readText()
                viewModel.selected.postValue(result)
            } catch (error: Error) {
                viewModel.selected.postValue(error.toString())
            }

    }
    log(this@MainActivity,result)