如何使用 id 从 Firebase RealTimeDatabase 获取数据

How to get data from Firebase RealTimeDatabase using id

提问人:HaBuiDuc 提问时间:11/13/2023 最后编辑:Frank van PuffelenHaBuiDuc 更新时间:11/13/2023 访问量:46

问:

我正在构建一个食品订购应用程序,我有一个 CartItem 列表

data class CartItemData(
  @PrimaryKey
  val cartItemId: String = UUID.randomUUID().mostSignificantBits.toString(),
  val userId: String,
  val foodId: String,
  val price: Double,
  val quantity: Int)

我想使用 cartItem 中的食物 ID 从 Firebase 实时数据库中检索食物数据,然后将其显示给用户。

这是我从数据库中获取食物数据的代码

fun getFood(
    foodId: String,
    onGetFoodSuccess: (FoodData) -> Unit
) {
    foodsRef.orderByChild("id").equalTo(foodId).addListenerForSingleValueEvent(object : ValueEventListener{
        override fun onDataChange(snapshot: DataSnapshot) {
            snapshot.children.forEach { shot ->
                Log.d(TAG, shot.value.toString())
                val data = shot.getValue(FoodData::class.java)
                data?.let(onGetFoodSuccess)
            }
        }

        override fun onCancelled(error: DatabaseError) {
        }

    })
}

这是我的购物车视图模型

class CartViewModel : ViewModel() {
  private val fireBaseRepository = FireBaseRepository.get()
  private val cartRepository = CartRepository.get()
  private val _cartState = MutableStateFlow(CartState())
  val cartState: StateFlow<CartState> = _cartState.asStateFlow()

  init {
      getCart()
  }

  fun getFood(
      foodId: String,
      onGetFoodSuccess: (FoodData) -> Unit
  ) {
      fireBaseRepository.getFood(
          foodId = foodId,
          onGetFoodSuccess = onGetFoodSuccess
      )
  }

  private fun getCart() {
      viewModelScope.launch {
          cartRepository.getCart().collect {cartItems ->
              _cartState.value = _cartState.value.copy(
                  cartItems = cartItems,
              )
          }
      }
  }
}

我不知道如何从实时数据库中检索数据并在从 SQLite 数据库中获取购物车数据后将其传递到我的视图。

Android Kotlin Firebase-实时数据库 android-jetpack-compose

评论

1赞 Frank van Puffelen 11/13/2023
你已经共享了相当多的代码,但除此之外没有调试信息,它不起作用。我建议在本地调试代码,并告诉我们结果。如果在共享代码的每一行上设置断点,请在调试器中运行代码,然后检查每行上每个变量的值,哪一行没有执行预期操作的第一行?
1赞 Frank van Puffelen 11/13/2023
Android 文档中有一个很棒的页面,介绍了如何调试应用,帮助您入门,其中包括有关使用断点检查可变值的部分。
0赞 HaBuiDuc 11/13/2023
我的getFood函数工作正常,实时数据库没有任何问题。但是,我不知道如何使用 foodId 检索食物数据,然后将其显示给用户。我有一个问题,即无法在可组合函数外部调用可组合函数,因此在成功检索数据后,我无法在getFood函数中创建视图。我的问题可能不清楚,因为我的英语水平不好。
0赞 Alex Mamo 11/13/2023
此代码中究竟有哪些内容不符合您的预期?告诉我们共享代码有什么问题。你有什么错误吗?请使用@AlexMamo回复

答:

0赞 Pablo 11/13/2023 #1

首先,我强烈建议您检查firebase是否正确检索快照,否则您的配置可能会有问题。此外,如果此时:

// code ...

foodsRef.orderByChild("id").equalTo(foodId).addListenerForSingleValueEvent(object : ValueEventListener{
        override fun onDataChange(snapshot: DataSnapshot) {
            snapshot.children.forEach { shot ->
                Log.d(TAG, shot.value.toString())
                val data = shot.getValue(FoodData::class.java)
                data?.let(onGetFoodSuccess)
            }
        }

        override fun onCancelled(error: DatabaseError) {
        }

    })

//code ...

这个日志正在检索数据,我可以假设主要问题出在这张地图上:,可能你打得不好, 因此,此值为 null 并且不回调。我的建议是检查firebase的快照结果,并检查您的数据类是否定义正确,提醒设置其默认值,否则应用程序将崩溃。查看此文档以获取更多解释。val data = shot.getValue(FoodData::class.java)FoodData

现在,如果你的问题是处理回调以检索到UI,那就更简单了。 您可以在 compose 视图中使用 cartState,并将 collect 作为可组合项的状态,因此每次此 stateFlow 更改其值时,都会重新绘制可组合项,请查看: https://developer.android.com/jetpack/compose/state#use-other-types-of-state-in-jetpack-compose

评论

0赞 HaBuiDuc 11/13/2023
我的 FoodData 定义正确,我的 getFood 函数正确检索数据,并且数据不为 null。但是,我尝试在 cartState 中定义一个 FoodData 列表并在成功检索 cartItemData 时更新它,但我的可组合项没有侦听 foodData 更新。不过,它可以接收带有 cartItemData 的更新。
0赞 Pablo 11/13/2023
尝试使用 stateFlow,就像您用于 _cartState 一样,但现在用于 getFood。并在 ui 上使用它,例如: ' fun getFood( foodId: String, ) { fireBaseRepository.getFood( foodId = foodId, onGetFoodSuccess = { _foodState.value = it } ) } '
0赞 HaBuiDuc 11/13/2023
它仍然不起作用。我的 UI 无法接收来自 FoodData 的更新。此外,我只声明了一个 cartState 变量来存储 CartScreen 的状态。我需要foodData来显示食物的名称和图像,因为我只将foodId存储在CartItem中。
0赞 Pablo 11/13/2023
所以你需要一个新的状态来重新组合并正确显示新数据,我认为你误解了可组合状态,你需要更新这个状态来用新数据更新组合。您需要调用此方法 getFood 并更新新的状态变量_foodState并在要使用 FoodData 的屏幕中使用它,这应该足够了。此外,分享您正在使用状态变量的屏幕代码。
0赞 HaBuiDuc 11/13/2023
但我认为 cartState 是一种状态,它的每次更改都会触发 UI。我以这种方式编写了一些状态,它工作得很好,我只对这个视图模型有问题。此外,请检查我的新问题以清楚地查看代码,因为我在此问题中没有提供 cartState 类。