База данных Firebase уведомляет адаптер после получения данных - PullRequest
0 голосов
/ 31 октября 2018

Я пытаюсь получить доступ к данным после их полного извлечения из базы данных? изначально я применяю адаптер к фрагменту. С помощью адаптера я пытался извлечь данные из базы данных Firebase. Так что тут давай проблему отправь нулевому массиву. После получения полных данных он должен отправить массив обратно?

Код адаптера:

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)


    }

}
}

Код получения информации:

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
}

1 Ответ

0 голосов
/ 31 октября 2018

Вы не можете вернуть то, что еще не было загружено. Другими словами, вы не можете просто вернуть список data как результат функции, потому что список всегда будет empty из-за асинхронного поведения этой функции. Это означает, что к тому времени, когда вы пытаетесь вернуть этот результат, данные еще не закончили загрузку из базы данных, и поэтому они недоступны.

По сути, вы пытаетесь вернуть значение синхронно из API, который является асинхронным. Это не очень хорошая идея. Вы должны обрабатывать API-интерфейсы асинхронно, как и предполагалось.

Быстрое решение этой проблемы - использовать список data только внутри обратного вызова (внутри метода onDataChange()). Если вы хотите использовать его снаружи, я рекомендую вам посмотреть последнюю часть моего ответа от этого поста , в котором я объяснил, как это можно сделать с помощью пользовательского обратного вызова. Вы также можете взглянуть на это видео для лучшего понимания.

...