[英]Kotlin wait for async with coroutine
I would like to open a new activity when phoneViewModel and ScanViewModel are instantiated.我想在 phoneViewModel 和 ScanViewModel 实例化时打开一个新活动。 They are instantiated by calling an async function InitialRead().
它们通过调用异步函数 InitialRead() 来实例化。 I'm logging each step, atm they are logged as done3 => done2 => done1
我正在记录每一步,atm 它们被记录为 done3 => done2 => done1
I would like to have them in this order: done1 => done2 => done3我想按以下顺序排列它们:done1 => done2 => done3
I have following code:我有以下代码:
class MainBusinessActivity : AppCompatActivity() {
private lateinit var scanViewModel: ScanViewModel
private lateinit var phoneViewModel: PhoneViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main_business)
}
private fun startEntitySetListActivity() = GlobalScope.async {
val sapServiceManager = (application as SAPWizardApplication).sapServiceManager
sapServiceManager?.openODataStore {
phoneViewModel = ViewModelProvider(this@MainBusinessActivity).get(PhoneViewModel::class.java).also {it.initialRead{Log.e("done", "done1")}}
scanViewModel = ViewModelProvider(this@MainBusinessActivity).get(ScanViewModel::class.java).also {it.initialRead{Log.e("done", "done2")}}
}
}
override fun onResume() {
super.onResume()
//startEntitySetListActivity()
runBlocking {
startEntitySetListActivity().await()
val intent = Intent(this@MainBusinessActivity, HomeActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
Log.e("done", "done3")
startActivity(intent)
}
}
} }
What am I doing wrong?我究竟做错了什么? Can someone correct my code?
有人可以更正我的代码吗?
Never use runBlocking
in an Android app.切勿在 Android 应用中使用
runBlocking
。 runBlocking
completely defeats the purpose of using coroutines, and can lead to an ANR. runBlocking
完全违背了使用协程的目的,并可能导致 ANR。 You also probably should never use GlobalScope
, which leads to UI leaks.您也可能永远不应该使用
GlobalScope
,这会导致 UI 泄漏。 You might possibly need it for some kind of long-running task that doesn't make sense to put in a service but doesn't have dependency on any UI components, but I can't think of any examples您可能需要它来执行某种长时间运行的任务,这些任务对放入服务没有意义但不依赖于任何 UI 组件,但我想不出任何例子
You also shouldn't be instantiating your ViewModels in the background.您也不应该在后台实例化您的 ViewModel。 That should be done in
onCreate()
.这应该在
onCreate()
。
Make this function a suspend function, and it can break down the two tasks in the background simultaneously before returning.将该函数设为挂起函数,可以在后台同时分解两个任务,然后返回。
Start your coroutine with lifecycleScope
.先从你的协同程序
lifecycleScope
。
Assuming sapServiceManager?.openODataStore
is an asynchronous task that takes a callback, you will need to wrap it in suspendCoroutine
.假设
sapServiceManager?.openODataStore
是一个需要回调的异步任务,您需要将它包装在suspendCoroutine
。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main_business)
phoneViewModel = ViewModelProvider(this@MainBusinessActivity).get(PhoneViewModel::class.java)
scanViewModel = ViewModelProvider(this@MainBusinessActivity).get(ScanViewModel::class.java)
}
private suspend fun startEntitySetListActivity() = coroutineScope {
val sapServiceManager = (application as SAPWizardApplication).sapServiceManager
sapServiceManager ?: return
suspendCoroutine<Unit> { continuation ->
sapServiceManager.openODataStore { continuation.resume(Unit) }
}
listOf(
launch {
phoneViewModel.initialRead{Log.e("done", "done1")}
},
launch {
scanViewModel.initialRead{Log.e("done", "done2")}
}
).joinAll()
}
override fun onResume() {
super.onResume()
lifecycleScope.launch {
startEntitySetListActivity()
val intent = Intent(this@MainBusinessActivity, HomeActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
Log.e("done", "done3")
startActivity(intent)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.