何时以及如何从 Android Activity 调用挂起功能?

use*_*615 7 android kotlin kotlin-coroutines

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

suspend fun retrieveInfo():String 
Run Code Online (Sandbox Code Playgroud)

我尝试调用 inside onCreateonResume但运行时崩溃。

runBlocking { 
    retrieveInfo()
}
Run Code Online (Sandbox Code Playgroud)
    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)

Run Code Online (Sandbox Code Playgroud)

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

Bar*_*ski 7

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

因此,如果您runBlockingActivity回调中调用,您的挂起块将在主线程上执行,您无法从中访问网络(查询服务器)。

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

runBlocking {
    withContext(Dispatchers.IO) {
        retrieveInfo()
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  1. 阅读Coroutines on Android(本部分及以下部分)

2.不要runBlocking用于你的情况,而是定义一个正确的job和使用job.launch{}

  • 不是真的,请提供一个更好的:( (2认同)