Mauricio Zimmermann
Mauricio Zimmermann

Reputation: 25

Unable to get nested data from Firestore and display it in a Recyclerview

Scenario

Absolute noob when it comes to actual programming here, trying to build an app on his own, learning as I code.

I've got a document that has a list of transactions underneath. This is my data structure

Collection: Transactions
 -> Document: Jan2021
   -> Map: <"transactions", ArrayList(Transaction[amount: String, date: Timestamp, description: String, type: String])>

Requirement

I want to show the transaction's description, date, and amount on a card (part of the "Transaction" data class).

Problem

I'm unable to (or maybe have no clue on how to do this) get the data and display it even in an AlertDialog, let alone get the data and map it to objects in the system.

Code being used

Custom Data Class

data class TransactionDocument (
    var Document: HashMap<String, Any> = hashMapOf()
)

MainActivity

val query: Query = traRef.whereEqualTo(FieldPath.documentId(), currentMonth)
val options =
    FirestoreRecyclerOptions.Builder<TransactionDocument>()
    .setQuery(query, TransactionDocument::class.java)
    .build()

val arr_trans: fb_adpt_transaction? = fb_adpt_transaction(options)

[...]

    override fun onStart() {
    super.onStart()
        arr_trans!!.startListening()
}

override fun onStop() {
    super.onStop()

    if (arr_trans != null) {
        arr_trans!!.stopListening()
    }
}

Adapter Class

class fb_adpt_transaccion constructor(transactionsList: FirestoreRecyclerOptions<TransactionDocument>):
    FirestoreRecyclerAdapter<TransactionDocument, fb_adpt_transaccion.TransactionViewHolder>(transactionsList)
{
    inner class TransactionsViewHolder constructor(private val view: View) : RecyclerView.ViewHolder(view) {

        fun displayValues(transaction: TransactionDocument, position: Int) {
            AlertDialog.Builder(this.view.context).setMessage(transaction.toString()).show()
        }
    }

    override fun onBindViewHolder( transactionViewHolder: fb_adpt_transaccion.TransactionsViewHolder,
        position: Int,modelo: TransactionDocument)
    {
        transactionViewHolder.mostrarValores(modelo, position)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): fb_adpt_transaction.TransactionViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.rv_transactions_view, parent, false)
        return TransactionViewHolder(view)
    }
}

What I've tested so far

If I try the below code in MainActivity, the result displayed is correct, but I'm somehow not able to make this work within the Adapter:

query.get().addOnSuccessListener {
    val message = it.documents[0]["transactions"].toString()

    AlertDialog.Builder(this).setMessage(message).show()
}

Additionally, I've tested changing the data class "TransactionDocument" (shown above) to Map, rather than HashMap. I've also tried sending a DocumentSnapshot (which doesn't work and it's just wrong).

Any help is appreciated!

Upvotes: 2

Views: 320

Answers (1)

Alex Mamo
Alex Mamo

Reputation: 138824

The problem in your code lies in the fact that the "transactions" property in your document is not a Map, is actually an array of "Transaction" objects. If you want to map that array into a list of custom objects, you can check the following article where I have explained:

How to map an array of objects from Cloud Firestore to a List of objects?

In your case, simply create a class:

class TransactionDocument {
    public List<Transaction> transactions;
}

And get the corresponding list using:

transactionIdRef.get().addOnCompleteListener(task -> {
    if (task.isSuccessful()) {
        DocumentSnapshot document = task.getResult();
        if (document.exists()) {
            List<Transaction> transactions = document.toObject(TransactionDocument.class).transactions;
            //Use the the list
        }
    }
});

Upvotes: 2

Related Questions