Android 协程流的回调未触发
Android callback for a coroutine flow is not fired
我有一项服务,其中数据由 MutableLiveData 支持并通过流暴露给外部。
@ApplicationScope
@Singleton
class UserProfileServiceImpl : UserProfileService {
private var userLiveData: MutableLiveData<UserProfile?> = MutableLiveData()
override fun currentUser() = userLiveData.value
override fun updatePoints(points: Int) {
val user = currentUser()
?: throw IllegalAccessException("user is not authenticated")
user.points = points
userLiveData.postValue(user)
}
override suspend fun currentUserFlow(): Flow<UserProfile?> =
callbackFlow {
userLiveData.observeForever {
offer(it)
}
}
}
然后我监听片段的视图模型中的变化并且没有调用回调
class ViewModel: ViewModel() {
fun startListeningToService() {
viewModelScope.launch {
profileService.currentUserFlow().collect {
// This is not getting fired
// Send data to another liveData that the activity is listening to
}
}
}
}
- 我是不是把事情搞复杂了?感觉穿越了很多层
数据从一点到另一点?使用 a 真的有优势吗?
流到这里?感觉只使用 LiveData 就可以了
更简单,不需要在两者之间进行转换
- 即使这不是最好的设计,为什么没有触发回调?
首先,如果你使用的是androidx.lifecycle:lifecycle-livedata-ktx
神器,你可以简单地使用liveData.asFlow()
如果您确实想使用 callbackFlow
滚动您的自定义实现,您需要在流程构建器中调用 awaitClose{...}
,否则它将被立即视为已完成。
override suspend fun currentUserFlow(): Flow<UserProfile?> =
callbackFlow {
val observer = Observer<UserProfile?>{
offer(it)
}
userLiveData.observeForever(observer)
awaitClose{
// called when the flow is no longer collected, e.g. the collecting
// CoroutineScope has been cancelled
userLiveData.removeObserver(observer)
}
}
我有一项服务,其中数据由 MutableLiveData 支持并通过流暴露给外部。
@ApplicationScope
@Singleton
class UserProfileServiceImpl : UserProfileService {
private var userLiveData: MutableLiveData<UserProfile?> = MutableLiveData()
override fun currentUser() = userLiveData.value
override fun updatePoints(points: Int) {
val user = currentUser()
?: throw IllegalAccessException("user is not authenticated")
user.points = points
userLiveData.postValue(user)
}
override suspend fun currentUserFlow(): Flow<UserProfile?> =
callbackFlow {
userLiveData.observeForever {
offer(it)
}
}
}
然后我监听片段的视图模型中的变化并且没有调用回调
class ViewModel: ViewModel() {
fun startListeningToService() {
viewModelScope.launch {
profileService.currentUserFlow().collect {
// This is not getting fired
// Send data to another liveData that the activity is listening to
}
}
}
}
- 我是不是把事情搞复杂了?感觉穿越了很多层 数据从一点到另一点?使用 a 真的有优势吗? 流到这里?感觉只使用 LiveData 就可以了 更简单,不需要在两者之间进行转换
- 即使这不是最好的设计,为什么没有触发回调?
首先,如果你使用的是androidx.lifecycle:lifecycle-livedata-ktx
神器,你可以简单地使用liveData.asFlow()
如果您确实想使用 callbackFlow
滚动您的自定义实现,您需要在流程构建器中调用 awaitClose{...}
,否则它将被立即视为已完成。
override suspend fun currentUserFlow(): Flow<UserProfile?> =
callbackFlow {
val observer = Observer<UserProfile?>{
offer(it)
}
userLiveData.observeForever(observer)
awaitClose{
// called when the flow is no longer collected, e.g. the collecting
// CoroutineScope has been cancelled
userLiveData.removeObserver(observer)
}
}