Reputation: 2196
I have a retry policy which takes in a lambda, launches a CoroutineScope
, increments a retry counter, checks if the maximum retries are reached, calculates a waitTime
based on the retry count, delays the scope for this time and finally calls the lambda:
fun connectionRetryPolicy(block: () -> Unit) {
Timber.d("connectionRetryPolicy: called")
// Launch the coroutine to wait for a specific delay
val scope = CoroutineScope(Job() + Dispatchers.Main)
scope.launch {
// Get and increment the current retry counter
val counter = retryCounter.getAndIncrement()
// Check if the counter is smaller than the maximum retry count and if so, wait a bit and execute the given function
if (counter < maxRetry) {
// Calculate the time to be waited
val waitTime: Long = (2f.pow(counter) * baseDelayMillis).toLong()
// Delay the scope for the calculated time
delay(waitTime)
// Execute the given function
block()
}
// Else, throw an exception
else {
throw FirebaseNetworkException("Retry count reached")
}
}
}
This method is called to recursively call a suspend function as the lambda, like this:
private suspend fun connectToGooglePlayBillingService(): BillingResult? {
Timber.d("connectToGooglePlayBillingService: called")
return suspendCoroutine { continuation ->
// If the billingClient is not already ready, start the connection
if (!playStoreBillingClient.isReady) {
// Start the connection and wait for its result in the listener
playStoreBillingClient.startConnection(object: BillingClientStateListener {
override fun onBillingServiceDisconnected() {
Timber.d("onBillingServiceDisconnected: called")
// Retry to connect using the RetryPolicies
RetryPolicies.connectionRetryPolicy { connectToGooglePlayBillingService() }
}
override fun onBillingSetupFinished(billingResult: BillingResult?) {
// There is code that does not matter here
}
})
}
}
}
Now, Lint tells me, that connectToGooglePlayBillingService
cannot be called inside the lambda because it's a suspend function and it needs to be called inside a CoroutineScope
. And as you can see, I do call the lambda inside a CoroutineScope
in connectionRetryPolicy
.
Is this a bug in Lint or do I do something wrong here? I know, I can create a new CoroutineScope
inside the lambda and then call connectToGooglePlayBillingService
and I am not sure if this is so wise, regarding performance.
Upvotes: 5
Views: 1532
Reputation: 8371
Replace
fun connectionRetryPolicy(block: () -> Unit)
with
fun connectionRetryPolicy(block: suspend () -> Unit)
Because your block()
will run inside a coroutine, but the other method doesn't know that.
Upvotes: 9