I experience strange lockups (freezes) when running coroutines. Sometimes it works perfectly fine, sometimes it will just wait and continue running after a long time (or not at all). I don't know If my setup is incorrect, there is some race condition or maybe I misunderstand how coroutines are supposed to be used. The app itself doesn't freeze or crash, it's just the coroutines stop/pause execution.
For example, in this bit the scope.launch would sometimes just not continue executing into billingClientDeferred.await()
override suspend fun getPurchases(): Result<List<Purchase>> = suspendCoroutine { continuation ->
scope.launch {
billingClientDeferred.await().success { client ->
client.queryPurchasesAsync(BillingClient.SkuType.SUBS) Subs@{ billingResultSubs, purchasesSubs ->
if (billingResultSubs.responseCode != BillingClient.BillingResponseCode.OK) {
continuation.resume(Result.Failure.Unknown())
return@Subs
}
continuation.resume(Result.Success(purchasesSubs))
}
}
}
}
scope is declared as:
private val scope = CoroutineScope(Job() + Dispatchers.Default)
Then it is called from WalletManager
override suspend fun verifyProducts(): Result<Unit> = billingProvider.getPurchases()
.successSuspend { purchases ->
purchases.forEach {
activatePurchase(it)
}
}.map { }
Which in the end is called from a ViewModel like this
override fun verify() {
viewModelScope.launch {
userSupervisor.walletManager.mapResult {
it.verifyProducts()
}
}
}
I'm guessing there is some issue with the combination of what dispatchers and scopes I'm using. I was trying different things with Dispatchers.Default, Dispatchers.Main, conforming class to CoroutineScope, using global scopes, but I always run into some threading/lockup issues I don't fully understand.