Reputation: 99
I would like to open a new activity when phoneViewModel and ScanViewModel are instantiated. They are instantiated by calling an async function InitialRead(). I'm logging each step, atm they are logged as done3 => done2 => done1
I would like to have them in this order: 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?
Upvotes: 1
Views: 2139
Reputation: 93511
Never use runBlocking
in an Android app. runBlocking
completely defeats the purpose of using coroutines, and can lead to an ANR. You also probably should never use GlobalScope
, which leads to UI leaks. 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
You also shouldn't be instantiating your ViewModels in the background. That should be done in 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
.
Assuming sapServiceManager?.openODataStore
is an asynchronous task that takes a callback, you will need to wrap it in 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)
}
}
Upvotes: 2