0

I am trying to iterate through the database documents and have the fields update with the click of the next button and previous button. As of right now, it's only happening with one and then it stops. I don't know why it only does it once and stops. Any reason as to why? Here is a snapshot of what I got right now.

enter image description here

This image is hardcoded in there with the code that is below here.

[![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")
            }
        }

However, I want to be able to implement these two buttons, so I can get rid of the code above and have it just pull from the database and navigate through each Post with the click of the buttons. I added this onto my next button and it is able to iterate only once. Is there a way that I can iterate through the size of the documents, that way I can go through all of them and not just once?

 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 { 
        
    }

Here is a snapshot of my database.

enter image description here

Again, to clarify, I am trying to iterate through my database with the Posts with the click of those buttons. Also, the images are stored in a firebase storage database since it's too large for firestore.

Adan Vivero
  • 422
  • 12
  • 36
  • Sounds like you're looking to paginate the data, which in Firestore works based on so-called cursors as explained here: https://firebase.google.com/docs/firestore/query-data/query-cursors – Frank van Puffelen Dec 16 '21 at 01:03
  • @FrankvanPuffelen I've encountered that page numerous of times before asking this question. It provides some information, but not exactly on the task that I am trying to perform with my buttons. – Adan Vivero Dec 16 '21 at 21:38

2 Answers2

1

As also @FrankvanPuffelen mentioned in his comment, what you are looking for is a pagination algorithm. Since all your images are represented by a documents inside the "Post" collection, it means that you can create a query to load a single image and then load all subsequent images one at a time.

I have answered a similar question a few years ago, where the OP wanted to load more results on a button click:

In your case, the first query would be:

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

To construct the second query, inside the first callback you have to get the last visible item using:

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

And perform the query:

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

inside this function:

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. 
                }
            }
        }
    }
Adan Vivero
  • 422
  • 12
  • 36
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
0

Here is how I solved this using my method onto my 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)
        }
}

And then with the private functions:

 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)
        }
    }
Adan Vivero
  • 422
  • 12
  • 36