简体   繁体   English

Kotlin 等待与协程的异步

[英]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.

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