简体   繁体   English

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

[英]When and how to call suspend function from Android Activity?

I have a suspend function that calls POST request to the server.我有一个调用 POST 请求到服务器的suspend函数。 I want to configure some text in the activity to show the information I received from the server.我想在活动中配置一些文本来显示我从服务器收到的信息。

suspend fun retrieveInfo():String 

I tried calling inside onCreate , onResume but crashes runtime.我尝试在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)

Where am I suppose to put these suspend calls (in which part of lifecycle of activity)?我想把这些挂起调用放在哪里(在活动生命周期的哪个部分)? Should I be using something other than runBlocking ?我应该使用runBlocking以外的其他东西吗?

By default runBlocking runs the suspending code block in the thread runBlocking was called on.默认情况下, runBlocking在调用runBlocking的线程中运行挂起的代码block

So if you called runBlocking from the Activity callback your suspending block will be executed on the main thread, from which you cannot access network (query a server).因此,如果您从Activity回调中调用runBlocking ,您的挂起块将在主线程上执行,您无法从中访问网络(查询服务器)。

You need to switch a dispatcher in your coroutine block for that call.您需要在协程块中为该调用切换调度程序。 The simplest fix for your code would be to move the execution to the Dispatchers.IO .最简单的代码修复方法是将执行移至Dispatchers.IO

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

That being said, I suggest two things (not related directly to your question):话虽如此,我建议两件事(与您的问题没有直接关系):

  1. Read Coroutines on Android (this part and the following ones)阅读Coroutines on Android (本部分和以下部分)

2. Don't use runBlocking for your case, but define a correct job and use job.launch{} 2. 不要在你的情况下使用runBlocking ,而是定义一个正确的job并使用job.launch{}

If you want to write in activity:如果你想在活动中写:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM