[英]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.我尝试在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)
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):话虽如此,我建议两件事(与您的问题没有直接关系):
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.