skip to Main Content

I want to populate a RecyclerView with data from Firebase. I tried something, I built an Adapter and tried to populate the RecyclerView but not showing any data in the RecyclerView and I get no errors.

In firebase console shows like the query is working but in the simulator not show anything and i dont ger errors.

[![The Recyclerview from the simulator][1]][1]

My layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".CamionesActivos">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvCamioness"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginStart="10dp"
        android:layout_marginTop="7dp"
        android:layout_marginEnd="10dp"
        android:layout_marginBottom="7dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:listitem="@layout/tarjeta_recycler" />
</androidx.constraintlayout.widget.ConstraintLay

my adapter:

class AdaptadorCamiones(private val camionlist:ArrayList<datos>)
    :RecyclerView.Adapter<AdaptadorCamiones.MyViewHolder>() {
    class MyViewHolder(itemView: View):RecyclerView.ViewHolder(itemView){
        val placa :TextView?=itemView.findViewById(R.id.tvPlacaDato)
        val peso: TextView?=itemView.findViewById(R.id.tvPesoDato)

    }

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

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        holder.placa?.text ?: camionlist[position].Placa
        holder.peso?.text ?: camionlist[position].Peso
    }

    override fun getItemCount(): Int {
        return camionlist.size
    }
}

my activity:

class CamionesActivos : AppCompatActivity() {
    private lateinit var recyclerView: RecyclerView
    private lateinit var camionList: ArrayList<datos>
    private var db=Firebase.firestore

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_camiones_activos)
        recyclerView=findViewById(R.id.rvCamioness)
        recyclerView.layoutManager=LinearLayoutManager(this, LinearLayoutManager.VERTICAL ,false)
        camionList= arrayListOf()
        recyclerView.adapter = AdaptadorCamiones(camionList)




        db=FirebaseFirestore.getInstance()
        db.collection("Camiones")
            .get()
            .addOnSuccessListener {
                if(!it.isEmpty){
                    for (data in it.documents){
                        val camion: datos? =data.toObject(datos::class.java)
                        if (camion !=null){
                            camionList.add(camion)
                        }

                    }

                }


            }

            .addOnFailureListener{
                Toast.makeText(this, it.toString(), Toast.LENGTH_SHORT).show()
            }
    }

}```


  [1]: https://i.stack.imgur.com/6xmfX.png

2

Answers


  1. Chosen as BEST ANSWER

    @cincy_anddeveloper

    i changed the main code using notifyItemInserted(position) but noting happens and the console shows a error

    main code:

    class CamionesActivos : AppCompatActivity() {
        private lateinit var recyclerView: RecyclerView
        private lateinit var camionList: ArrayList<datos>
        private lateinit var adapter: AdaptadorCamiones
        private lateinit var linearLayoutManager: LinearLayoutManager
    
        private var db=Firebase.firestore
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_camiones_activos)
            recyclerView=findViewById(R.id.rvCamioness)
            linearLayoutManager = LinearLayoutManager(this)
            recyclerView.layoutManager = linearLayoutManager
                 //recyclerView.layoutManager=LinearLayoutManager(this, 
                LinearLayoutManager.VERTICAL ,false)
            camionList= arrayListOf()
            adapter= AdaptadorCamiones(camionList)
            recyclerView.adapter=adapter
            db=FirebaseFirestore.getInstance()
            db.collection("Camiones")
                .get()
                .addOnSuccessListener {
                    if(!it.isEmpty){
                        for (data in it.documents){
                            val camion: datos? =data.toObject(datos::class.java)
                            if (camion !=null){
                                camionList.add(camion)
                                adapter.notifyItemInserted(camionList.size+1)
                            }
                        }
                    }
                }
                .addOnFailureListener{
                    Toast.makeText(this, it.toString(), Toast.LENGTH_SHORT).show()
                }
        }
    }
    

    Console error:

    E/RecyclerView: No adapter attached; skipping layout
    

  2. The reason why data isn’t displaying is because the RecyclerView’s adapter (AdaptadorCamiones) isn’t aware that it’s dataset (camionList) has been updated. Whenever you insert data into the collection that backs the RecyclerView’s adapter you need to inform it that a change by calling one of it’s many notify…(…) methods. The quick and dirty solution would be to call notifyDataSetChanged() and it will trigger the RecyclerView to be redrawn and you’re new data will be at the bottom of the list.

    The proper solution would be to use the of the adapters notifyItemInserted(int) overload. This method will inform the adapter that a single item was inserted at the given position. The adapter will trigger the RecyclerView to efficiently update and animate the new item into the specified position.

    Calling notifyDataSetChanged() will force the RecyclerView’s layout manager to rebind all view and relayout all visible items. Unless you’re using stable IDs the RecycleView will not animate any structural changes using this method. Using the more specific notify… overloads will always be more efficient. There are overloads for notify the adapter of several items being inserted, as well as the reciprocal methods for removing one or many items. There are also overloads to notify the adapter of that items have been updated or swapped positions. By calling this overloads instead of notifyDataSetChanged() the RecyclerView will be able to animate the structural changes.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search