英文:
How to fix the error Suspension functions can be called only within coroutine body when I invoke a suspend fun in setOnInfoListener?
问题
以下是代码的翻译部分:
以下代码用于在Android Studio项目中记录声音并将项目保存到数据库中,使用了Room。当达到设置的最大持续时间并且已经达到时,系统将自动停止记录并将项目保存到数据库中。
但是,代码收到了以下错误信息:
“只能在协程体内调用悬挂函数”
我应该如何修复它?
override suspend fun startRecord(updateElapsedTime: UpdateElapsedTime) {
with(mRecorder) {
setAudioSource(MediaRecorder.AudioSource.MIC);
setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
setMaxDuration(1000 * 60 * recordMaxValue);
setOutputFile(filename);
setOnInfoListener { mr, what, extra ->
if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
completeRecord(updateElapsedTime) //它导致错误
}
}
prepare()
start()
}
}
override suspend fun completeRecord(updateElapsedTime: UpdateElapsedTime) {
try {
mRecorder.stop()
} catch (e: Exception) {
}
saveRecord()
}
private suspend fun saveRecord() {
val mInfo = MInfo()
handleMInfo.add(mInfo)
}
英文:
The following code is to record a sound and save an item to database in Android Studio project with Room, and system will stop record and save item to database automatically when a maximum duration had been setup and has now been reached.
But the code receives the error information:
Suspension functions can be called only within coroutine body
How can I fix it?
override suspend fun startRecord(updateElapsedTime: UpdateElapsedTime) {
with(mRecorder) {
setAudioSource(MediaRecorder.AudioSource.MIC);
setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
setMaxDuration(1000 * 60 * recordMaxValue);
setOutputFile(filename);
setOnInfoListener { mr, what, extra ->
if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
completeRecord(updateElapsedTime) //It causes error
}
}
prepare()
start()
}
}
override suspend fun completeRecord(updateElapsedTime: UpdateElapsedTime) {
try {
mRecorder.stop()
} catch (e: Exception) {
}
saveRecord()
}
private suspend fun saveRecord() {
val mInfo = MInfo()
handleMInfo.add(mInfo)
}
答案1
得分: 2
你传递给 setOnInfoListener
的这个 lambda 表达式并不在你的协程内调用。它会在监听器所在类期望的任何线程上被调用。
(对于 MediaRecorder,它会在用于实例化 MediaRecorder 的任何线程上被调用,除非那不是一个 LooperThread,在这种情况下它会在主线程上调用。)
由于监听器代码不在你的协程内调用,你不能在其中调用挂起函数。你必须在监听器中启动一个新的协程来调用挂起函数。如果你想避免泄漏 MediaRecorder,你必须使用适用于你的 MediaRecorder 生命周期的 CoroutineScope。
英文:
This lambda you pass to setOnInfoListener
is not called inside your coroutine. It's called on whatever thread the listener's class wants to.
(In the case of MediaRecorder, it will be called on whatever thread was used to instantiate the MediaRecorder, unless that wasn't a LooperThread, in which case it will call it on the main thread.)
Since the listener code is not called in your coroutine, you cannot call suspend functions in it. You must launch a new coroutine in the listener to call a suspend function. You must use a CoroutineScope that is appropriate for the lifetime of your MediaRecorder if you want to avoid leaking the MediaRecorder.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论