3

I have a project that I work and I use Firebase Firestore. I have added from mysql database 125 items to Cloud firestore. I searched Firebase online presentation to get informations but for some reason it is not helping me. I see web, swift, c and also php but i can not see code for KOTLIN. But after 3 day of work I displayed items in logcat. Another problem is, I searched presentation, stackoverflow there is no indication how to diplay data in RecyclerView. How can I display items to RecyclerView with KOTLIN?

I want to know how to do this with Kotlin.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193

1 Answers1

13

As I understand from your question, you have successfully displayed the items in your logcat, right? So in this case there are two more steps that you need to do in order to display the data in a RecyclerView.

The first step would be to create a custom adapter or if you want you can use FirestoreRecyclerAdapter and the second one is to create a holder class for your item. In the end just set the adapter to your RecyclerView and that's it.

Solution added:

For Java delopers, this is a recommended way in which you can retrieve data from a Cloud Firestore database and display it in a RecyclerView using FirestoreRecyclerAdapter.

For Kotlin developers, I'll adapt the code from the example above. Assuming you have a Firestore database structure that looks like this:

Firestore-root
    |
    --- products (collection)
           |
           --- documentIdOne (document)
           |        |
           |        --- productName: "Milk"
           |
           --- documentIdTwo (document)
           |        |
           |        --- productName: "Soy Milk"
           |
           --- documentIdThree (document)
                    |
                    --- productName: "Bacon"

A model class that looks also like this:

class ProductModel (val productName: String = "")

And a .XML file that contains a RecyclerView which also looks like this:

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/recycler_view"/>

To display all the product names, please follow the next steps.

Now you need to find the RecyclerView in your activity and set the LinearLayoutManager but first you need the following import:

import kotlinx.android.synthetic.main.activity_main.*

And then just use the following line of code:

recycler_view.layoutManager = LinearLayoutManager(this)

In which recycler_view is actually the id of the RecyclerView as seen in the .XML file above.

Then you need to create the root reference of your Firestore database and a Query object like this:

val rootRef = FirebaseFirestore.getInstance()
val query = rootRef!!.collection("products").orderBy("productName", Query.Direction.ASCENDING)

Then you'll have to create a FirestoreRecyclerOptions object like this:

val options = FirestoreRecyclerOptions.Builder<ProductModel>().setQuery(query, ProductModel::class.java).build()

In your activity class, create a holder class that looks like this:

private inner class ProductViewHolder internal constructor(private val view: View) : RecyclerView.ViewHolder(view) {
    internal fun setProductName(productName: String) {
        val textView = view.findViewById<TextView>(R.id.text_view)
        textView.text = productName
    }
}

Now we need to create an adapter class which in this case should look like this:

private inner class ProductFirestoreRecyclerAdapter internal constructor(options: FirestoreRecyclerOptions<ProductModel>) : FirestoreRecyclerAdapter<ProductModel, ProductViewHolder>(options) {
    override fun onBindViewHolder(productViewHolder: ProductViewHolder, position: Int, productModel: ProductModel) {
        productViewHolder.setProductName(productModel.productName)
    }

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

Your item_product .XML file should like this:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/text_view""/>

Then create an adapter field which is declared as global:

private var adapter: ProductFirestoreRecyclerAdapter? = null

And instantiate it in your activity like this:

adapter = ProductFirestoreRecyclerAdapter(options)
recycler_view.adapter = adapter

In the end, don't forget to override the following two functions and start listening for changes:

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

override fun onStop() {
    super.onStop()

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

The result is this:

enter image description here

As you can see using Kotlin, the code is even simpler and are less lines of code but remember official documentations will never provide you particular code, you'll have to create your self.

jamix
  • 5,484
  • 5
  • 26
  • 35
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Thanks but that here is information in java, i search in KOTLIN. Can you help me with KOTLIN? – Divyansh Jayesh Aug 08 '18 at 12:46
  • You can simply copy Java code and paste it in your IDE and will be coverted in Kotlin code, right? – Alex Mamo Aug 08 '18 at 12:51
  • I tried to do this but is not working. Please help me with KOTLIN. – Divyansh Jayesh Aug 08 '18 at 14:12
  • Without seeing some code of yours and if you don't provide the behaviour or the errors that you get, I cannot be much of a help. But I will try to provide you a quick adaptation of that example. – Alex Mamo Aug 08 '18 at 14:22
  • Please see my updated answer but if something else comes up when implementing it, please post another fresh question, so me and other users can help you. – Alex Mamo Aug 08 '18 at 15:10
  • @AlexMamo , how I can get the id of each products? currently I get the id by updating it to each record after I successfully create one record. but maybe you can inform me simpler way? – Dika Mar 28 '20 at 02:32
  • 1
    @Dika You can simply store the id of the products as a property in your document and then use it like this: `productViewHolder.setProductId(productModel.productId) ` – Alex Mamo Mar 28 '20 at 11:33
  • thank you, @AlexMamo . I assume there is no other way – Dika Mar 29 '20 at 03:15
  • I had a bit of trial and error to figure out what you meant by creating an `adapter` field declared as global, but I think I got it working. I know it is a lot to write out something fully working for someone, but there are many of us that appreciate your efforts. Thank you! @AlexMamo – sirEgghead May 15 '22 at 00:49
  • @sirEgghead You're very welcome, sirEgghead. – Alex Mamo May 15 '22 at 08:09