如何在 Android Studio 中使用 Kotlin 从 Firestore 数据库中获取下一条和上一条数据?

Posted

技术标签:

【中文标题】如何在 Android Studio 中使用 Kotlin 从 Firestore 数据库中获取下一条和上一条数据?【英文标题】:How to get the Next and Previous piece of data from the Firestore Database using Kotlin in Android Studio? 【发布时间】:2022-01-19 01:51:55 【问题描述】:

我正在尝试遍历数据库文档并通过单击下一个按钮和上一个按钮来更新字段。截至目前,它只发生在一个上,然后就停止了。我不知道为什么它只执行一次并停止。有什么理由吗?这是我现在得到的快照。

这张图片是用下面这里的代码硬编码的。

[![private lateinit var locationTextView: TextView
    private lateinit var descriptionTextView: TextView
    private lateinit var previousArrow: Button
    private lateinit var nextArrow: Button
    private lateinit var usersImage: ImageView][2]][2]

val db = FirebaseFirestore.getInstance()
db.collection("Post").orderBy("timestamp")
    val docRef = db.collection("Post").document("Puppy")
    docRef.get()
        .addOnSuccessListener  document ->
            if (document != null) 
                Log.d("Exists", "DocumentSnapshot data: $document.data")

               // locationTextView.text = document.getString("locationTitle")
                locationTextView.setText(document.getString("Name"))
                descriptionTextView.setText(document.getString("description"))
                val imageName = "Puppy"
                val storageRef = FirebaseStorage.getInstance().reference.child("Images/$imageName")

                val localFile = File.createTempFile("tempImage", "jpeg")
                storageRef.getFile(localFile).addOnSuccessListener 

                    val bitmap = BitmapFactory.decodeFile(localFile.absolutePath)
                    usersImage.setImageBitmap(bitmap)
                
            
            else 
                Log.d("noExist", "No Such Document")
            
        

但是,我希望能够实现这两个按钮,因此我可以摆脱上面的代码,让它从数据库中提取并通过单击按钮浏览每个帖子。我将它添加到我的下一个按钮上,它只能迭代一次。有没有一种方法可以遍历文档的大小,这样我可以遍历所有文档而不仅仅是一次?

 nextArrow.setOnClickListener 


val first = db.collection("Post").orderBy("timestamp").limit(1)
            first.get()
                .addOnSuccessListener  documentSnapshots ->

                    val lastVisible = documentSnapshots.documents[documentSnapshots.size() - 1]
                    val next = db.collection("Post").orderBy("timestamp").startAfter(lastVisible).limit(2)
                        next.get().addOnSuccessListener  documents ->
                            for (document in documents) 
                                Log.d(TAG, "$document.id => $$document.data")
                                locationTextView.setText(document.getString("Name"))
                                descriptionTextView.setText(document.getString("description"))
                            
                        
                    val imageName = "Puppy"
                    val storageRef = FirebaseStorage.getInstance().reference.child("Images/$imageName")

                    val localFile = File.createTempFile("tempImage", "jpeg")
                    storageRef.getFile(localFile).addOnSuccessListener 
                        val bitmap = BitmapFactory.decodeFile(localFile.absolutePath)
                        usersImage.setImageBitmap(bitmap)
                    
                
    
    previousArrow.setOnClickListener  
        
    

这是我的数据库的快照。

再次澄清一下,我正在尝试通过单击这些按钮来遍历我的数据库。此外,图像存储在 firebase 存储数据库中,因为它对于 firestore 来说太大了。

【问题讨论】:

听起来您正在寻找分页数据,在 Firestore 中基于所谓的游标工作,如下所述:firebase.google.com/docs/firestore/query-data/query-cursors @FrankvanPuffelen 在问这个问题之前,我已经多次遇到该页面。它提供了一些信息,但不完全是关于我试图用我的按钮执行的任务。 【参考方案1】:

正如@FrankvanPuffelen 在他的评论中提到的,您正在寻找的是pagination algorithm。由于您的所有图像都由“Post”集合中的文档表示,这意味着您可以创建一个查询来加载单个图像,然后一次加载所有后续图像。

几年前我回答了一个类似的问题,OP 想要在单击按钮时加载更多结果:

Is there a way to paginate queries by combining query cursors using FirestoreRecyclerAdapter?

在您的情况下,第一个查询是:

val db = FirebaseFirestore.getInstance()
val firstQuery = db.collection("Post").orderBy("timestamp").limit(1)

要构造第二个查询,在第一个回调中,您必须使用以下方法获取最后一个可见项:

val lastVisible = queryDocumentSnapshots.documents[queryDocumentSnapshots.size() - indexFam]

并执行查询:

val next = db.collection("Post").orderBy("timestamp").startAfter(lastVisible).limit(1)

在这个函数内部:

private fun getNext(first: Query, db: FirebaseFirestore, indexFam: Int) 
        first.get().addOnSuccessListener  queryDocumentSnapshots ->
            val lastVisible = queryDocumentSnapshots.documents[queryDocumentSnapshots.size() - indexFam]
            val next = db.collection("Post").orderBy("timestamp").startAfter(lastVisible).limit(1)
            next.get().addOnSuccessListener  documents ->
                for (document in documents) 
                    Log.d(TAG, "$document.id => $$document.data")
                    // Whatever you want to iterate right here. 
                
            
        
    

【讨论】:

什么是声明的“任务”? lastVisible 会进入 addOnSuccessListener 吗? “任务”是来自 onComplete 的参数。请查看linked answer。试一试,告诉我它是否有效。 那是在 Java 中... 您可以简单地将 Java 代码转换为 Kotlin 代码。 我找到了我的解决方案。我只需要不断更新 lastvisible 的数量就可以继续下降。【参考方案2】:

这是我在 onCreate() 上使用我的方法解决这个问题的方法:

private lateinit var locationTextView: TextView
private lateinit var descriptionTextView: TextView
private lateinit var previousArrow: Button
private lateinit var nextArrow: Button
private lateinit var usersImage: ImageView

val db = FirebaseFirestore.getInstance()
val first = db.collection("Post").orderBy("timestamp")
getNext(first, db, 2) // This is the original pop up

getPostSizeAsync(first)  postSize ->
  nextArrow.setOnClickListener 
           nextClicker++
      if(nextClicker == postSize) 
           nextClicker = 2
      
      getNext(first, db, nextClicker)
      



// This is for the previous button clicker
previousArrow.setOnClickListener 
        if(nextClicker > 1)
        
            nextClicker--
            getNext(first, db, nextClicker)
        

然后是私有函数:

 private fun getNext(first: Query, db: FirebaseFirestore, indexFam: Int) 
        first.get().addOnSuccessListener  queryDocumentSnapshots ->
            val lastVisible = queryDocumentSnapshots.documents[queryDocumentSnapshots.size() - indexFam]
            val next = db.collection("Post").orderBy("timestamp").startAfter(lastVisible).limit(1)
            next.get().addOnSuccessListener  documents ->
                for (document in documents) 
                    Log.d(TAG, "$document.id => $$document.data")
                    locationTextView.setText(document.getString("Name"))
                    descriptionTextView.setText(document.getString("description"))
                    val imageName = document.getString("Name")
                    val storageRef = FirebaseStorage.getInstance().reference.child("Images/$imageName")
                    val localFile = File.createTempFile("tempImage", "jpeg")
                    storageRef.getFile(localFile).addOnSuccessListener 
                        val bitmap = BitmapFactory.decodeFile(localFile.absolutePath)
                        usersImage.setImageBitmap(bitmap)
                    
                
            
        
    
private fun getPostSizeAsync(first: Query, callback: (Int) -> Unit) 
        first.get().addOnSuccessListener  documents ->
            val postSize = documents.count()
            callback(postSize)
        
    

【讨论】:

以上是关于如何在 Android Studio 中使用 Kotlin 从 Firestore 数据库中获取下一条和上一条数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何在模块(Android Studio)中使用 com.android.databinding?

如何在android应用里执行adb 命令

如何在 Android Studio 中使用我自己的 Android.mk 文件

如何在所有活动中使用Android Studio默认导航抽屉[重复]

如何在Android Studio中使用YouTube API在Android应用中列出视频

如何在visual studio开发android程序