当前位置: 首页 > 知识库问答 >
问题:

如何在jetpack compose文本视图[重复]中显示Firestore集合文档中的文档字段

李新霁
2023-03-14

如果我违反了一些规则,或者之前有人问过我,我很抱歉。我花了很多时间在谷歌上搜索示例,以及有关堆栈溢出和其他资源的问题。但我无法理解如何从firestore集合中获取文档字段,并在jetpack compose文本函数中显示字符串值。

我是编程和Android的初学者。所以我有一些基本的误解,我应该怎么做,但这是我的尝试,它不起作用,我不明白为什么。

在FiRecovery中,我有一个集合,称为用户,其中包含一个名为holidaySavings的文档,其中有一个名为name的字符串字段。

我想在可组合的文本函数中显示name的值。

我有一个名为storedData的类来处理Firestore。它具有创建和更新集合/文档/字段的方法。这很有效。

但我似乎无法从文档中读取字段值到jetpack可组合文本。

我可以从一个文档字段读取值,并在Android studio中读取日志。

这是我在类中处理Firestore数据库的函数

fun readDataTestFinal(): String{
        val docRef = db.collection("users").document("holidaySavings")
        var returnTest = ""
        docRef.get()
            .addOnSuccessListener { document ->
                if (document != null) {
                    Log.d("Rtest", "DocumentSnapshot data: ${document.data}")

                    // I want to return this so I can use it in a composable text view
                    returnTest = document.get("name").toString()
                } else {
                    Log.d("Rtest", "No such document")
                }
            }
            .addOnFailureListener {  exception ->
                Log.d("Rfail", "get failed with ", exception)
            }
        return returnTest
    }

在这里,我尝试将值读入jetpack compose文本函数。

var newStringFromStoredData by remember {
                mutableStateOf(storedData().readDataTestFinal())
            }
            Text(
                modifier = Modifier.background(color = Color.Blue),
                text = newStringFromStoredData
            )

当我运行应用程序时。一切都编译得很好,我从文档字段fine中获得值,并可以在Android Studio的日志中看到它。

但是Compose函数在其中调用值newStringFromStoredData的Text它没有显示在屏幕上?

有谁能告诉我我不了解的是什么,以及如何使用firestore文档字段并在jetpack compose文本函数中显示值?

共有2个答案

慕容宇
2023-03-14

在您的情况下,最方便、最快捷、显然也是最好的补丁是使用所谓的valueEventListeners。

Firebase为您提供了这些有用的方法,以便您可以通过Firebase服务器使您的应用程序数据保持最新。

val docRef = db.collection("cities").document("SF")
docRef.addSnapshotListener { snapshot, e -> // e is for error

    // If error occurs
    if (e != null) {
        Log.w(TAG, "Listen failed.", e)
        return@addSnapshotListener
    }
    
    // If backend value not received, use this to get current local stored value
    val source = if (snapshot != null && snapshot.metadata.hasPendingWrites())
        "Local"
    else
        "Server"
    
    // If request was successful, 
    if (snapshot != null && snapshot.exists()) {
        Log.d(TAG, "$source data: ${snapshot.data}")
        //Update your text variable here
        newStringFromStoredData = snapshot.data // Might need type-conversion
    } else {
        Log.d(TAG, "$source data: null")
    }
}

这不仅可以解决问题中所述的问题,还可以确保每当服务器上的值发生更改/更新时,文本都会随之更新。使用这些监听器通常是一个很好的最佳实践,为了遵守“关注点分离”原则,这些监听器通常被转换为LiveData对象,但您可以将这个简单的实现用于所描述的简单用例。

另一件事,这通常会出现在viewModel中,因此,您也应该在viewModel中声明您的文本变量。在初始化块中尝试。

calss MVVM: ViewModel() {
  init {
    /* Paste Code From Above Here */
  }

  var newStringFromStoredData by mutableStateOf("") 

}

然后在Composable中阅读

<代码>文本(viewModel.newStringFromStoredData)

郁隐水
2023-03-14

Firebase调用是异步的,这意味着它不会立即返回数据。这就是API使用回调的原因。因此,您的函数readDataTestFinal总是返回一个空字符串。

您可以使用的一种解决方案是在一个挂起函数中转换您的函数,并使用协同路由范围调用它。例如:

suspend fun readDataTestFinal(): String {
    val docRef = firestore.collection("users")
        .document("holidaySavings")
    return suspendCoroutine { continuation ->
        docRef.get()
            .addOnSuccessListener { document ->
                if (document != null) {
                    continuation.resume(document.get("name").toString())
                } else {
                    continuation.resume("No such document")
                }
            }
            .addOnFailureListener { exception ->
                continuation.resumeWithException(exception)
            }
    }
}

在上面的代码中,我们将回调调用转换为挂起函数。

在composable中,可以执行以下操作:

var newStringFromStoredData by remember {
    mutableStateOf("")
}
Text(newStringFromStoredData)

LaunchedEffect(newStringFromStoredData) {
    newStringFromStoredData =
        try { readDataTestFinal() } catch(e: Exception) { "Error!" }
}

LaunchedEffect将启动挂起功能,并在加载后立即更新结果。

一个更好的选择是在视图模型中定义这个调用并从中调用这个函数。但我认为这回答了您的问题,您可以稍后改进您的架构。您可以从这里开始。

 类似资料:
  • 我必须在我的Android应用程序中列出Firebase Firestore文档中的所有字段。如何落实? 例如在附上的截图中,我必须在我的App中显示文档“HiySLB7YW0DGE5B1MMPigreByJ03”中的所有字段。 文档截图

  • 我的用户可以在子集合中创建文档(比如任务),并使用一系列安全规则检查身份验证、权限和数据有效性。他们甚至可以选择多个任务并将其复制到同一集合中。现在,一个普通用户可能一次最多创建100个任务,但如果有人恶意获取我的数据库凭据,进行身份验证,并尝试以编程方式创建大量有效文档,该怎么办?这将使Firestore的扩展不会出现问题,也会给我的Firebase账单带来意想不到的惊喜。这是我首先关心的问题,

  • 我如何删除一个特定的文档中的一个集合在fiRecovery使用反应? 我在这里和谷歌上看了看,但我没有发现任何内在相关的东西。 我只是设法从我的集合中删除索引[0]的文档。 这状态idDoc接收所有id文档。 如果我只是传递. doc(idDoc),我会得到以下错误: Firebase Error: Function Collection Reference.doc()要求它的第一个参数是非空字符

  • 我的FiRecovery数据库中有一个名为Reports的集合,我已经在其中添加了文档。但我现在的问题是我想在报表中添加一个带有子集合的文档,有什么想法吗?

  • 问题内容: 对于我的应用程序而言,至关重要的是能够从Firebase的集合中随机选择多个文档。 由于Firebase(我知道)没有内置本机函数来实现执行此操作的查询,因此我的第一个想法是使用查询游标选择随机的起始索引和终止索引,前提是我拥有​​其中的文档数集合。 这种方法行之有效,但只能以有限的方式进行,因为每次每次文档都会与其相邻文档一起依次送达。但是,如果我能够通过其父集合中的索引选择一个文档

  • 在我的集合的SnapshotListener中,我使用以下命令循环遍历文档: 在 for 循环中的每个文档中,让我们称之为 ,我在 Cloud Firestore 上还有另一个文档集合。我想检索内子集合中的所有文档(每个文档只有一个字符串字段)。我能够做一个来获取本身,我用它来获取字符串字段,但我不知道如何获取其子集合中的文档。