什么时候以及如何从Android Activity调用暂停功能?

时间:2019-07-06 09:23:51

标签: android kotlin kotlin-coroutines

我有一个suspend函数,它向服务器调用POST请求。我想在活动中配置一些文本,以显示我从服务器收到的信息。

suspend fun retrieveInfo():String 

我尝试在onCreateonResume内部调用,但崩溃了运行时。

runBlocking { 
    retrieveInfo()
}
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.google.augmentedimage/com.google.AugmentedImageActivity}: android.os.NetworkOnMainThreadException
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3086)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3229)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)

我应该将这些挂起调用放在哪里(在活动生命周期的哪个部分)?我应该使用runBlocking以外的其他东西吗?

2 个答案:

答案 0 :(得分:1)

默认情况下,runBlocking在被调用的线程block中运行挂起代码runBlocking

因此,如果您从runBlocking回调中调用了Activity,则您的暂停块将在主线程上执行,您无法从该主线程访问网络(查询服务器)。

您需要在协程中将调度程序切换为该调用。您的代码最简单的解决方法是将执行移至Dispatchers.IO

runBlocking {
    withContext(Dispatchers.IO) {
        retrieveInfo()
    }
}

话虽如此,我建议两件事(与您的问题不直接相关):

  1. 阅读Coroutines on Android(本部分和以下内容)

2。不要为您的情况使用runBlocking,而是要定义正确的job并使用job.launch{}

答案 1 :(得分:1)

如果要写活动:

class MyActivity : AppCompatActivity() {
private val scope = CoroutineScope(newSingleThreadContext("name"))

fun doSomething() {
    scope.launch { ... }
  }
}