【发布时间】:2021-01-24 10:20:56
【问题描述】:
我已经在suspendCancellableCoroutine中封装了一个回调来将它转换为一个挂起函数:
suspend fun TextToSpeech.speakAndWait(text: String) : Boolean {
val uniqueUtteranceId = getUniqueUtteranceId(text)
speak(text, TextToSpeech.QUEUE_FLUSH, null, uniqueUtteranceId)
return suspendCancellableCoroutine { continuation ->
this.setOnUtteranceProgressListener(object : JeLisUtteranceProgressListener() {
override fun onDone(utteranceId: String?) {
if(utteranceId == uniqueUtteranceId) {
Timber.d("word is read, resuming with the next word")
continuation.resume(true)
}
}
})
}
}
我正在使用片段的 lifecycleScope 协程范围调用此函数,并且我假设它在片段被销毁时被取消。但是,LeakCanary 报告说我的片段因为这个监听器而泄漏,我用日志验证了即使在协程被取消后也调用了回调。
所以似乎用suspendCancellableCoroutine而不是suspendCoroutine包装并不足以取消回调。我想我应该主动检查作业是否处于活动状态,但是如何?我尝试了coroutineContext.ensureActive() 并在回调中检查了coroutineContext.isActive,但 IDE 给出了一个错误,提示 “只能在协程主体内调用暂停函数”我还能做些什么来确保它不会如果作业被取消,是否继续?
【问题讨论】:
-
你有
continuation.invokeOnCancellation { callback.cancel() } -
谢谢,有帮助!我的回调没有取消方法,但我尝试在取消时删除侦听器并且它有效:
continuation.invokeOnCancellation { this.setOnUtteranceProgressListener(null) }没有更多泄漏!再次感谢!您想将其添加为答案吗?
标签: android callback kotlin-coroutines cancellation