Gilson Lim
Gilson Lim

Reputation: 27

Only Able to display the last subchild from firebase to my recycler view (Updated)

I am only able to display the last child in myCars into a recyclerView but I am not sure how i tried using for loop but i am not sure if that is the right way to write it

this is my data in Firebase

this is my code for GpsFragment.kt i tried to display my data here and i got an error which is

lateinit property cars has not been initialized

class GpsFragment : Fragment(), OnCarItemClickListener {
private var user = FirebaseAuth.getInstance().currentUser
val reqId = user!!.uid
lateinit var cars: List<Cars>
private val ref = FirebaseDatabase.getInstance().reference.child("users")

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    (context as AppCompatActivity).supportActionBar!!.title = "Gps"
    val root = inflater.inflate(R.layout.fragment_gps, container, false)

    return root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    addCarbtn.setOnClickListener {
        val intent = Intent(activity, AddCarActivity::class.java)
        activity?.startActivity(intent)
    }

    cars = emptyList()
    var adapter = CarAdapter(cars, this)
    myCarlist?.adapter = adapter
    showCars()

}

private fun showCars() {

    var carLat:String
    var carLng:String
    var name:String

    val query = ref.orderByChild("uid").equalTo(reqId)

    query.addListenerForSingleValueEvent(object : ValueEventListener {
        override fun onCancelled(p0: DatabaseError) {

        }

        override fun onDataChange(dataSnapshot: DataSnapshot) {
                for (childDss in dataSnapshot.children) {
                    for (subChildren in childDss.child("myCars").children){
                        val count = childDss.child("myCars").childrenCount.toInt()
                        carLat = (subChildren.child("carlat").getValue(String::class.java)).toString()
                        carLng = (subChildren.child("carlng").getValue(String::class.java)).toString()
                        name = (subChildren.child("carid").getValue(String::class.java)).toString()
                        Log.d("carlat",carLat.toString())
                        Log.d("carlng",carLng.toString())
                        Log.d("name",name.toString())

                        cars = listOf(
                            Cars(name.toString(), carLat.toString(), carLng.toString())
                        )

                    }
                }
            myCarlist?.layoutManager = LinearLayoutManager(activity)
            myCarlist?.adapter = CarAdapter(cars,this@GpsFragment)
            myCarlist.adapter?.notifyDataSetChanged()

        }

    })

}

override fun onItemClick(cars: Cars, position: Int) {
    val intent = Intent(context, TrackingActivity::class.java)
    intent.putExtra("CARNAME", cars.name)
    intent.putExtra("LAT", cars.latitude)
    intent.putExtra("LNG", cars.longtitude)

    startActivity(intent)
}

}

This is my code for Cars.kt

data class Cars(val name: String = "-",
            val latitude: String = "-",
            val longtitude: String = "-")

This is my code for CarAdapter.kt

class CarAdapter (private val cars : List<Cars>, var clickListener: OnCarItemClickListener) : RecyclerView.Adapter<CarAdapter.CarViewHolder>(){

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CarViewHolder {
    val inflater = LayoutInflater.from(parent.context).inflate(R.layout.list_layout, parent, false)

    return  CarViewHolder(inflater)
}

override fun getItemCount() = cars.size

override fun onBindViewHolder(holder: CarViewHolder, position: Int) {
    val car = cars[position]

    holder.initialize(cars.get(position),clickListener)

}

class CarViewHolder(val view:View) : RecyclerView.ViewHolder(view){

    var carName = view.carname
    var lat = view.latitude
    var lng = view.longtitude

    fun initialize(cars: Cars, action:OnCarItemClickListener){
        carName.text = cars.name
        lat.text = cars.latitude
        lng.text = cars.longtitude

        view.setOnClickListener{
            action.onItemClick(cars, adapterPosition)
        }

    }
}

}

interface OnCarItemClickListener{ fun onItemClick(cars: Cars, position: Int) }

Upvotes: 0

Views: 213

Answers (1)

Peter Haddad
Peter Haddad

Reputation: 80904

Firebase api is asynchronous, therefore when you are calling myCarlist?.adapter = CarAdapter(cars,this) is it getting called before the data is retrieved from the database, and since you are initializing cars inside the for loop, then you get the above error that it is not initialised yet. Therefore to solve this, you need to set the adapter inside onDataChange():

        override fun onDataChange(dataSnapshot: DataSnapshot) {
            if (dataSnapshot.exists())
            {
                for (childDss in dataSnapshot.children){
                    val count = childDss.child("myCar").childrenCount.toInt()
                    Log.d("count",count.toString())

                    for (i in 0 until count){
                        val carLat  = childDss.child("carlat").getValue(String::class.java)
                        val carLng  = childDss.child("carlng").getValue(String::class.java)
                        val name  = childDss.child("carid").getValue(String::class.java)

                        cars = listOf(
                            Cars(name.toString(),carLat.toString(),carLng.toString())
                        )

                    }
                      myCarlist?.adapter = CarAdapter(cars,this)
                }
            }
        }

Upvotes: 1

Related Questions