在不使用LiveData的情况下将数据从存储库返回到ViewModel



我只是想找到一个答案,如何将数据从Repository传递到ViewModel,而不需要像RxJava这样的额外依赖关系。LiveData在这里似乎不是一个好的解决方案,因为我不需要在我的Presentation中进行,只需要在ViewModel中进行,并且使用observeForever不是一个很好的做法。代码很简单:我使用Firebase示例尝试用Flow传递数据,但不能在侦听器中使用它(只有在协程主体内才能调用Suspension函数错误(:

存储库

fun fetchFirebaseFlow(): Flow<List<MyData>?> = flow {
var ret: List<MyData>? = null
firebaseDb.child("data").addListenerForSingleValueEvent(
object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val data = dataSnapshot.getValue<List<MyData>>()
emit(data) // Error. How to return the data here?
}
override fun onCancelled(databaseError: DatabaseError) {
emit(databaseError) // Error. How to return the data here?
}
})
//        emit(ret) // Useless here
}

ViewModel

private suspend fun fetchFirebase() {
repo.fetchFirebaseFlow().collect { data ->
if (!data.isNullOrEmpty()) {
// Add data to something
} else {
// Something else
}
}

您可以使用callbackFlow

@ExperimentalCoroutinesApi
fun fetchFirebaseFlow(): Flow<List<String>?> = callbackFlow {

val listener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val data = dataSnapshot.getValue<List<MyData>>()
offer(data)
}
override fun onCancelled(databaseError: DatabaseError) {

}
}
val ref =firebaseDb.child("data")
reef.addListenerForSingleValueEvent(listener)
awaitClose{
//remove listener here
ref.removeEventListener(listener)
}
}

ObservableField类似于LiveData,但不支持生命周期,可以用来代替创建Observable对象。

{
val data = repo.getObservable()
val cb = object : Observable.OnPropertyChangedCallback() {
override fun onPropertyChanged(observable: Observable, i: Int) {
observable.removeOnPropertyChangedCallback(this)
val neededData = (observable as ObservableField<*>).get()
}
}
data.addOnPropertyChangedCallback(cb)
}

fun getObservable(): ObservableField<List<MyData>> {
val ret = ObservableField<List<MyData>>()
firebaseDb.child("events").addListenerForSingleValueEvent(
object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
ret.set(dataSnapshot.getValue<List<MyData>>())
}
override fun onCancelled(databaseError: DatabaseError) {
ret.set(null)
}
})
return ret
}

也可以对单个结果使用suspendCancelLabelCoroutine。感谢Kotlin论坛。

最新更新