如何解决Firebase实时数据库和Kotlin协同程序
我是一个初学者,目前正在Kotlin上开发一个Android应用,该应用从TMDb获取数据 API,并使用Firebase Realtime数据库存储和检索数据。
我使用Kotlin协程从TMDb API获取数据,但是我不确定是否应该使用协程从Firebase实时数据库存储或检索数据。
我希望Firebase自动完成Kotlin协程的工作。
这是我要执行的Firebase操作之一:(从数据库中检索对象)
firebaseDatabase = Firebase.database
dbReference = firebaseDatabase.getReference("users/$uid")
val dbListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
// Get Post object and use the values to update the UI
val fobject = dataSnapshot.getValue<TvFirebase>()
Log.v("utk","tv show name is " + fobject!!.name)
// ...
}
override fun onCancelled(databaseError: DatabaseError) {
// Getting Post failed,log a message
Log.w("utk","onCancelled",databaseError.toException())
// ...
}
}
val tvReference = firebaseDatabase.getReference("users/$uid/tv/236")
tvReference.addValueEventListener(dbListener)
那么我需要在Firebase实时数据库中使用Kotlin协程吗?
解决方法
不需要将协程与任何Firebase API一起使用,但是,如果正确执行,无疑可以使您的开发更加轻松。但是,协程与报告随时间变化的值的Firebase侦听器不兼容。对于这些,您可能想要使用LiveData或Flow。
,只需在您的代码中做些小改动。
从这里...
firebaseDatabase = Firebase.database
dbReference = firebaseDatabase.getReference("users/$uid")
val dbListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
// Get Post object and use the values to update the UI
val fobject = dataSnapshot.getValue<TvFirebase>()
Log.v("utk","tv show name is " + fobject!!.name)
// ...
}
override fun onCancelled(databaseError: DatabaseError) {
// Getting Post failed,log a message
Log.w("utk","onCancelled",databaseError.toException())
// ...
}
}
val tvReference = firebaseDatabase.getReference("users/$uid/tv/236")
tvReference.addValueEventListener(dbListener)
对此...
val firebaseDatabase = FirebaseDatabase.getInstance().getReference("users/$uid")
firebaseDatabse.addChildEventListener(object: ChildEventListener {
override fun onChildAdded(snapshot: DataSnapshot,previousChildName: String?) {
Log.d("MainFragment","Children $snapshot")
}
override fun onChildChanged(snapshot: DataSnapshot,previousChildName: String?) {}
override fun onChildRemoved(snapshot: DataSnapshot) {}
override fun onChildMoved(snapshot: DataSnapshot,previousChildName: String?) {}
override fun onCancelled(error: DatabaseError) {}
})
别忘了检查它是否正确;)
,您可以使用callBackFlow API删除所有Firebase回调。 简单的例子:
override suspend fun getSomething(): Flow<Long> = callbackFlow {
val valueListener = object: ValueEventListener{
override fun onCancelled(error: DatabaseError) {
close()
}
override fun onDataChange(snapshot: DataSnapshot) {
offer(snapshot.childrenCount)
}
}
currentUserId?.let { userId ->
firebaseRef?.child(userId)?.addValueEventListener(valueListener)
?: offer(0) }
awaitClose {
currentUserId?.let { userId ->
firebaseRef?.child(userId)?.removeEventListener(valueListener)
}
}
}
,
我正在使用“实时数据库”和“ Firestore”在旧项目中添加一些新功能。
由于firestore在协程上支持“等待”挂起功能,因此我在Realtime数据库中搜索了同样的功能。如果您不混合使用暂停和回调函数,协程很好。.
最后自己做。 我还没有尝试下面的代码,但是它应该可以工作。
注意:自1.2.0起,某些功能仍被标记为ExperimentCoroutinesApi,因此请注意,如果将来发行版中它有所更改。
sealed class RealtimeDatabaseValueResult {
class Success(val dataSnapshot: DataSnapshot): RealtimeDatabaseValueResult()
class Error(val error: DatabaseError): RealtimeDatabaseValueResult()
}
/**
* Perform a addListenerForSingleValueEvent call on a databaseReference in a suspend function way
* @param onCancellation action to perform if there is a cancellation
*/
@ExperimentalCoroutinesApi
suspend fun DatabaseReference.awaitSingleValue(onCancellation: ((cause: Throwable) -> Unit)? = null) = suspendCancellableCoroutine<RealtimeDatabaseValueResult> { continuation ->
val valueEventListener = object: ValueEventListener{
override fun onCancelled(error: DatabaseError) {
continuation.resume(RealtimeDatabaseValueResult.Error(error = error),onCancellation)
}
override fun onDataChange(snapshot: DataSnapshot) {
continuation.resume(RealtimeDatabaseValueResult.Success(snapshot),onCancellation)
}
}
// add listener like you normally do
addListenerForSingleValueEvent(valueEventListener)
// in case the job,coroutine,etc. is cancelled,we remove the current event listener
continuation.invokeOnCancellation { removeEventListener(valueEventListener) }
}
用法:
fun fetchUser(firebaseDatabase: FirebaseDatabase,userId: String){
CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate).launch{
when(val result = firebaseDatabase.getReference("users").child(userId).awaitSingleValue()){
is RealtimeDatabaseValueResult.Success -> {
val dataSnapshot: DataSnapshot = result.dataSnapshot
// proceed action with dataSnapshot
}
is RealtimeDatabaseValueResult.Error -> {
val error: DatabaseError = result.error
// proceed action with error
}
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。