我有一个suspend
函数,它向服务器调用POST请求。我想在活动中配置一些文本,以显示我从服务器收到的信息。
suspend fun retrieveInfo():String
我尝试在onCreate
,onResume
内部调用,但崩溃了运行时。
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
以外的其他东西吗?
答案 0 :(得分:1)
默认情况下,runBlocking
在被调用的线程block
中运行挂起代码runBlocking
。
因此,如果您从runBlocking
回调中调用了Activity
,则您的暂停块将在主线程上执行,您无法从该主线程访问网络(查询服务器)。
您需要在协程中将调度程序切换为该调用。您的代码最简单的解决方法是将执行移至Dispatchers.IO
。
runBlocking {
withContext(Dispatchers.IO) {
retrieveInfo()
}
}
话虽如此,我建议两件事(与您的问题不直接相关):
Coroutines on Android
(本部分和以下内容) 2。不要为您的情况使用runBlocking
,而是要定义正确的job
并使用job.launch{}
答案 1 :(得分:1)
如果要写活动:
class MyActivity : AppCompatActivity() {
private val scope = CoroutineScope(newSingleThreadContext("name"))
fun doSomething() {
scope.launch { ... }
}
}