让我从示例代码片段开始
suspend fun executeLive(result: MutableLiveData<Person>) {
val response = ... //suspend api request
mediatorLiveData.removeSource(response)
mediatorLiveData.addSource(response) {
result.value = sortData(it) // sortData is also suspend function which sortData at Dispatcher.Default
}
}
在这个例子中,sortData
不能在lambda function
下调用(在这个例子中是addSource
)。而且我已经将executeLive
声明为suspend
,这就是为什么suspend
API请求可以首先启动。但是sortData
函数显示编译时错误
挂起函数只能从协程体调用
那么,如何改变代码结构来解决这个问题呢?
**更新:**是否有相关文章?
3条答案
按热度按时间svgewumm1#
lambda通常是一个回调函数。回调函数之所以被称为回调函数,是因为我们在函数中 Package 了一段代码,并将其传递给其他人(或其他地方)执行。这是一个基本的控制反转,其中代码不是由你执行,而是由其他人执行(例如框架)。
例如,当你在一个按钮上设置一个
onClickListener
,我们不知道它什么时候会被调用,我们为框架传递一个lambda,它负责用户交互来调用指定的动作。在你的例子中,suspend函数也没有调用
sortdata
,而是把它传递给mediatorLiveData
对象,在它自己的上下文中调用它。你传递的lambda函数不一定要从协程体调用,因此这是不允许的。rn0zuynd2#
您可以通过使用
suspendCoroutine
将mediatorLiveData.addSource
调用转换为挂起调用本身来解决此问题:我使用
TypeOfData
作为response
发出的数据类型的占位符。注意,这只适用于您打算进行单次发射的情况。如果需要跟踪多个值,可以使用
callbackFlow
进行实验:zc0qhyus3#
以下是3个工作示例:
第一:
第二:
最后一个-使用
runBlocking { }
但在这种情况下,您将阻塞当前线程,直到执行协程: