Как отобразить загрузку элементов во время выборки данных из Firebase android kotlin

#android #firebase #kotlin #firebase-realtime-database #android-recyclerview

#Android #firebase #kotlin #firebase-база данных в реальном времени #android-recyclerview

Вопрос:

У меня есть RecyclerView и мой Fragment . Я получаю данные из Firebase Realtime Database в RecyclerView.

Мне нужно сделать так, чтобы во время загрузки данных я видел какой-то эффект загрузки. Как я могу это сделать?

Код из моего Fragment:

 private var _binding: FragmentDayDetailBinding? = null
private val binding get() = _binding!!

private var ref: DatabaseReference? = null
private lateinit var adapter: DayDetailAdapter

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    _binding = FragmentDayDetailBinding.inflate(inflater, container, false)

    setupRecyclerView()
    initDatabase()

    return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    readFromDatabase()
}

private fun setupRecyclerView() {
    adapter = DayDetailAdapter()
    binding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
    binding.recyclerView.adapter = adapter
}

private fun initDatabase() {
    FirebaseApp.initializeApp(requireContext())

    ref = FirebaseDatabase.getInstance()
        .getReference("IMIT")
        .child("groups")
}

private fun readFromDatabase() {
    ref?.addValueEventListener(object: ValueEventListener {
        override fun onDataChange(snapshot: DataSnapshot) {
            if (snapshot.exists()) {

                val list = ArrayList<Day>()

                for (daySnapshot in snapshot.children) {
                    val day = daySnapshot.getValue(Day::class.java)

                    list.add(day!!)
                }

                adapter.submitList(list)

            } else {
                binding.apply {
                    lrDbEmpty.visibility = View.VISIBLE
                    recyclerView.visibility = View.INVISIBLE
                }
            }
        }

        override fun onCancelled(error: DatabaseError) {

        }
    })
}

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}
 

Код из RecyclerView Adapter:

 class ViewHolder(private val binding: ItemSubjectDetailBinding): RecyclerView.ViewHolder(binding.root) {

    fun bind(day: Day) = with(binding) {
        tvSubject.text = day.subject
        tvInfo.text = "${day.teacher}, ${day.type}"
        tvTime.text = day.time
        tvAud.text = day.classroom
    }

    companion object {
        fun from(parent: ViewGroup): ViewHolder {
            val layoutInflater = LayoutInflater.from(parent.context)
            val binding = ItemSubjectDetailBinding.inflate(layoutInflater, parent, false)
            return ViewHolder(binding)
        }
    }
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    return ViewHolder.from(parent)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    with(holder) {
        bind(getItem(position))
    }
}

class ItemComparator: DiffUtil.ItemCallback<Day>() {
    override fun areItemsTheSame(oldItem: Day, newItem: Day): Boolean {
        return oldItem == newItem
    }

    override fun areContentsTheSame(oldItem: Day, newItem: Day): Boolean {
        return oldItem == newItem
    }
}
 

Комментарии:

1. Что именно в этом коде работает не так, как вы ожидаете? Расскажите нам, что не так с общим кодом. У вас есть какие-либо ошибки?

2. Я также думаю, что это репозиторий может помочь.

3. @AlexMamo вау, это репозиторий мне очень поможет, спасибо

Ответ №1:

Вы уже на полпути

Создайте панель прогресса в центре фрагмента

 <ProgressBar
      android:id="@ id/progress_bar"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      />
 

Держите его видимым до тех пор, пока данные не будут извлечены ( onDataChange вызваны), затем скройте панель прогресса

 override fun onDataChange(snapshot: DataSnapshot) {

    binding.progressBar.visibility = View.GONE

    if (snapshot.exists()) {
        // rest of your code
    }
}