0

I am trying to access data once it is completely retrieved from database? initially I apply adapter to fragment. With in the Adapter I tried to retrieve data from firebase database. So here give problem it send the null arraylist. It should send back the arraylist when complete data is retrieved?

Adapter code :

class FirebaseAdapter(context: Context): RecyclerView.Adapter<FirebaseAdapter.Holder>() {

var dataList: ArrayList<DatabaseOperations.ImageInfo> = arrayListOf()
var context: Context? = null

init {
    if (context == null)
        this.context = context

    dataList= DatabaseOperations().retriveInfo(context!!)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
    var itemView: View = LayoutInflater.from(parent.context).inflate(R.layout.imagelist_row,parent)
    var viewHolder: FirebaseAdapter.Holder = FirebaseAdapter.Holder(itemView)


    return viewHolder
}

override fun getItemCount(): Int {
    Log.e("itemCoutn",dataList.size.toString()) // it give output 0
    return dataList.size
}

override fun onBindViewHolder(holder: Holder, position: Int) {

   try {
       //----------------get bitmap from image url-----------------
       var downloadUri: String = dataList.get(position).downloadUri
       Log.e("fire adapter",downloadUri.toString())

       //------------------Assign Data to item here-----------------
       holder.image_name.text = dataList.get(position).imageName

       Glide.with(this!!.context!!)
               .load(downloadUri)
               .into(holder.row_image)

   }
   catch(e: Exception){
       Log.e("Firebase Adapter","Error "+e.toString())
   }
}


class Holder(itemView: View?) : RecyclerView.ViewHolder(itemView) {

    val row_image: ImageView
    val image_name: TextView
    init {

        row_image  = itemView!!.findViewById<ImageView>(R.id.row_image)
        image_name = itemView!!.findViewById<TextView>(R.id.image_name)


    }

}
}

Information retrieve code :

fun retriveInfo( context: Context): ArrayList<ImageInfo>{

    var data = ArrayList<ImageInfo>()

    if (mDatabaseRefrence == null)
        mDatabaseRefrence = FirebaseDatabase.getInstance().getReference(getUid())

    val menuListener = object : ValueEventListener {
        override fun onDataChange(dataSnapshot: DataSnapshot) {

            var dataSnap: DataSnapshot? = null


            var it: Iterable<DataSnapshot> = dataSnapshot.children
            it.forEach { dataSnapshot ->
                data.add(ImageInfo(
                        dataSnapshot!!.child("imageName").toString(),
                        dataSnapshot!!.child("imageInfo").toString(),
                        dataSnapshot!!.child("downloadUri").toString()
                ))
            }

            FirebaseAdapter(context).notifyDataSetChanged()
            Log.e("db size 0",data.size.toString())

        }

        override fun onCancelled(databaseError: DatabaseError) {
            println("loadPost:onCancelled ${databaseError.toException()}")
        }
    }

    mDatabaseRefrence!!.addValueEventListener(menuListener)



    Log.e("db size",data.size.toString())

    return data
}
Abhishek Borikar
  • 374
  • 1
  • 5
  • 15
  • In which part of your code, at which line is your ArrayList `null`? – Alex Mamo Oct 31 '18 at 15:47
  • In retrieve information code there is arraylist called data. In method onDataChange I am populating the data arraylist but arraylist received init section in firebase adapter is null – Abhishek Borikar Oct 31 '18 at 15:54

1 Answers1

0

You cannot return something now that hasn't been loaded yet. With other words, you cannot simply return the data list as a result of a function because the list it will always be empty due the asynchronous behaviour of this function. This means that by the time you are trying to return that result, the data hasn't finished loading yet from the database and that's why is not accessible.

Basically, you're trying to return a value synchronously from an API that's asynchronous. That's not a good idea. You should handle the APIs asynchronously as intended.

A quick solve for this problem would be to use the data list only inside the callback (inside the onDataChange() method). If you want to use it outside, I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.

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