【问题标题】:RecyclerView load after doing action and not as the fragment loadsRecyclerView 在执行操作后加载,而不是在片段加载时加载
【发布时间】:2020-09-27 06:34:55
【问题描述】:

我已经在谷歌上搜索了一段时间来解决我的问题,但我找不到任何解决方案。 我的 RecyclerView getItemCount() 返回 0 并且只有在我在几个片段之间切换并返回片段后,我才在适配器加载中使用 RecyclerView 并返回真实的项目编号。 我确实将记录器放在了我的 getList 函数中,即使这些项目也被推送到我的数组中,也就是命令数组。 size return 0...我真的找不到解决办法。

这是一些可以使用的代码 顺便说一句->当我使用 SQLite 时,我第一次使用 FireBaseDataBase,我没有遇到 recycler 视图的问题。 如果你需要更多代码让我知道 非常感谢!人们在这里帮助我:) 片段代码:

package com.seanCo.DeliveryApp.fragments

import android.app.Activity
import android.app.AlertDialog
import android.content.Context
import android.content.DialogInterface
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
import android.os.Parcel
import android.os.Parcelable
import android.renderscript.Sampler
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.View.inflate
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AlertDialogLayout
import androidx.core.content.res.ColorStateListInflaterCompat.inflate
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.ValueEventListener
import com.seanCo.DeliveryApp.R
import kotlinx.android.synthetic.main.adding_delivery.*
import kotlinx.android.synthetic.main.adding_delivery.view.*
import kotlinx.android.synthetic.main.fragment_active_delivery.*
import java.sql.Date
import java.sql.Time
import java.text.SimpleDateFormat
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.format.DateTimeFormatter

class activeDeliveryFragment(db : DatabaseReference) : Fragment() {

    val tempDB = db
    var deliveryID = 0
    var tempList : MutableList<deliveryInfo> = ArrayList()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        val cView = inflater.inflate(R.layout.fragment_active_delivery, container, false)
        val tView= activity

        findId()
        val toolbarTitle = tView?.findViewById<TextView>(R.id.toolbar_title)
        val toolbar = tView?.findViewById<androidx.appcompat.widget.Toolbar>(R.id.toolbar)
        val text = toolbarTitle?.setText("משלוחים פעילים")

        val delivery = deliveryInfo()
        val addButton = cView.findViewById<ImageButton>(R.id.plus_button)
        addButton.setOnClickListener{

            val dialog = AlertDialog.Builder(getContext())
            val dialogView = layoutInflater.inflate(R.layout.adding_delivery, null)
            dialog.setView(dialogView)
            val dialogData = dialog.show()

            dialogView.dialog_pos.setOnClickListener{
                dialogData.dismiss()
                delivery.address = dialogData.et_address.text.toString()
                val timer = setTime((dialogData.et_timer.text.toString()).toInt())
                delivery.timer = timer
                deliveryID++
                val array : Array<Any> = arrayOf(delivery.address, delivery.timer)
                Log.i("tag", delivery.timer.toString())
                tempDB.child("activeDeliveryies/$deliveryID").child("addess").setValue(delivery.address)


            }

            dialogView.dialog_neg.setOnClickListener{
                dialogData.dismiss()
            }

        }


        return cView
    }

    override fun onResume() {
        refreshList()
        return super.onResume()
    }


    override fun onActivityCreated(savedInstanceState: Bundle?) {

        rv_activeDelivery.layoutManager = LinearLayoutManager(activity)
        return super.onActivityCreated(savedInstanceState)
    }


    fun refreshList(){
        getList()
        rv_activeDelivery.adapter = rvAdapater(requireContext(), this, tempList)
    }

    fun getList(){
        tempDB.child("activeDeliveryies").addValueEventListener( object : ValueEventListener{
            override fun onCancelled(error: DatabaseError) {
            }

            override fun onDataChange(snapshot: DataSnapshot) {
                for(id in snapshot.children){
                    val temp = id.key.toString().toInt()
                    if(temp > tempList.size) {
                        for (address in snapshot.child(id.key.toString()).children) {
                            val infoList = deliveryInfo()
                            infoList.address = address.getValue().toString()
                            tempList.add(infoList)
                            Log.i("first", address.getValue().toString())

                        }
                    }
                }

            }
        })

    }

    fun setTime(timer : Int) : Int{
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
           var getTime = LocalDateTime.now()
           var hours = getTime.hour
           var minutes = getTime.minute + timer
           if(minutes >= 60){
               minutes -= 60
               hours += 1
           }
             val newTime = "$hours$minutes"
           return newTime.toInt()
        } else {

           var date = java.util.Date()
           val formatter = SimpleDateFormat("HH:mm")
           val answer: String = formatter.format(date)
           return 0
        }

    }

    fun findId(){
        tempDB.child("activeDeliveryies").addValueEventListener( object : ValueEventListener{
            override fun onCancelled(error: DatabaseError) {
                TODO("Not yet implemented")
            }

            override fun onDataChange(snapshot: DataSnapshot) {

                for(id in snapshot.children){
                    deliveryID = (id.key.toString()).toInt()

                }
            }
        })
    }

    class rvAdapater(val context : Context,val activeDelivery : activeDeliveryFragment,val list : MutableList<deliveryInfo>) : RecyclerView.Adapter<rvAdapater.ViewHolder>(){
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            return ViewHolder(LayoutInflater.from(activeDelivery.context).inflate(R.layout.rv_child_activedelivery, parent, false))
        }

        override fun getItemCount(): Int {
            Log.i("tag", list.size.toString())
            return list.size
        }

        override fun onBindViewHolder(holder: rvAdapater.ViewHolder, position: Int) {
            holder.deliveryAddress.text = list[position].address
        }

        class ViewHolder(v : View) : RecyclerView.ViewHolder(v){

            val deliveryAddress : TextView = v.findViewById(R.id.tv_address)

        }
    }


}

更新:

    fun refreshList(){
        getList()
        rv_activeDelivery.adapter?.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
            override fun onChanged() {
                super.onChanged()
                Log.d("frag", "numberOfItems: " + rv_activeDelivery.adapter?.getItemCount())
            }
        })
        rv_activeDelivery.adapter = rvAdapater(requireContext(), this, tempList)
        (rv_activeDelivery.adapter as rvAdapater).notifyDataSetChanged()

    }

更新:找到解决方案: 我只是更改了 refreshList 方法中命令的顺序

  fun refreshList(){
        val con = this
        tempDB.child("activeDeliveryies").addValueEventListener( object : ValueEventListener{
            override fun onCancelled(error: DatabaseError) {
            }

            override fun onDataChange(snapshot: DataSnapshot) {

                Log.i("datachanged", "data")
                for(id in snapshot.children){
                    val temp = id.key.toString().toInt()
                    if(temp > tempList.size) {
                        for (address in snapshot.child(id.key.toString()).children) {
                            val infoList = deliveryInfo()
                            infoList.address = address.getValue().toString()
                            tempList.add(infoList)

                        }
                    }
                }
                rv_activeDelivery.adapter = rvAdapater(requireContext(), con, tempList)
                val temp = (rv_activeDelivery.adapter as rvAdapater)
                
            }
        })


    }

【问题讨论】:

  • 您的 refreshList() 方法仅在所有内容完成加载 (onResume()) 后才会调用。您可以考虑重构代码以在 onCreate() 方法中调用 refreshList()。

标签: android firebase kotlin firebase-realtime-database android-recyclerview


【解决方案1】:

数据是从 Firebase 实时数据库异步加载的,这意味着您不能简单地直接在适配器对象上调用 getItemCount(),因为它始终是。所以为了得到项目的总数,你需要像下面的代码行一样注册一个观察者:

rv_activeDelivery.adapter.registerAdapterDataObserver(object : AdapterDataObserver() {
    override fun onChanged() {
        super.onChanged()
        Log.d("TAG", "numberOfItems: " + rv_activeDelivery.adapter.getItemCount())
    }
})

对于 Java 用户:

adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
    @Override
    public void onChanged() {
        super.onChanged();
        Log.d("TAG", "numberOfItems: " + adapter.getItemCount());
    }
});

【讨论】:

  • 首先感谢您的回答,非常感谢。我对dataObserver不太熟悉,所以我真的不知道把你发给我的代码放在哪里,也不明白它到底是如何解决我的问题的。当我使用我在此处共享的代码加载我的程序时,我的 recyclerList 仅在我在片段之间切换后才会显示。请帮我找到解决方案,我不必这样做才能看到列表。
  • 您应该在需要显示项目数量的确切位置使用此代码。但是不要忘记,数据是异步加载的,所以需要一些时间才能找到可用的项目数。
  • 我不需要显示项目的数量。我需要获取函数“getItemCount”以在我的片段加载后返回列表中的真实项目数,而不是在一段时间后
  • 请不要让我一个人在这里解决我的问题 xD 我知道我很难
  • 我不需要显示项目的数量。我需要获取函数“getItemCount”来返回项目的实际数量,是的,这就是你应该继续使用的解决方案。
猜你喜欢
  • 1970-01-01
  • 2016-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多