Reputation: 11344
I have a suspendable (updateData
) function which takes another suspend function as an argument (transform
). In my updateData
function I'm making a call to an asynchronous API and I need to pass the result to the transform
suspend function.
My current problem is that calling the transform
function shows the message "suspension functions can be called only within coroutine context".
Here's what the code looks like:
override suspend fun updateData(transform: suspend (prefs: Preferences) -> Preferences): Preferences {
return suspendCancellableCoroutine { continuation ->
realtimeDatabase.runTransaction(object : Transaction.Handler {
override fun doTransaction(currentData: MutableData): Transaction.Result {
val prefs: Preferences = currentData.toPreferences()
// I need to call the transform() function here
// transform(prefs)
// This call shows the error "suspension functions can be called only within coroutine context"
return Transaction.success(currentData)
}
override fun onComplete(
error: DatabaseError?,
committed: Boolean,
currentData: DataSnapshot?
) {
if (error != null) {
continuation.resumeWithException(error)
} else {
continuation.resume(currentData.toPreferences())
}
}
})
}
}
I found this similar question, but it doesn't really solve my problem because I can't call the transform
function outside of doTransaction
(I need currentData
).
Also, I can't make transform
a normal "non-suspend" function because I'm overriding that function from another class.
My question is: How can I apply the transform
suspend function to currentData
?
Upvotes: 2
Views: 1436
Reputation: 93834
I don't know exactly what your API is here, but maybe you can break this function up to do your transformation after the suspendCoroutine
block so its being called inside the coroutine instead of in the API callback.
override suspend fun updateData(transform: suspend (prefs: Preferences) -> Preferences): Preferences {
val retrievedPrefs = suspendCancellableCoroutine { continuation ->
realtimeDatabase.runTransaction(object : Transaction.Handler {
override fun doTransaction(currentData: MutableData): Transaction.Result {
return Transaction.success(currentData)
}
override fun onComplete(
error: DatabaseError?,
committed: Boolean,
currentData: DataSnapshot?
) {
if (error != null) {
continuation.resumeWithException(error)
} else {
continuation.resume(currentData.toPreferences())
}
}
})
}
return transform(retrievedPrefs)
}
Upvotes: -1