You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio中Kotlin实现Fragment用RecyclerView展示Firebase数据问题

问题描述

我有一个带导航栏和Fragment的Activity,在其中一个Fragment中向Firebase存储数据,希望在另一个Fragment中用RecyclerView展示这些数据。参照YouTube教程实现后,目标Fragment显示空白,附上相关代码寻求帮助。

相关代码

数据类

data class Event(var eventName: String, var eventTime:String?=null)

ViewModel

class EventViewModel :ViewModel() {
    private val repository : EventRepository
    private val _allEvents = MutableLiveData<List<Event>>()
    val allEvents : LiveData<List<Event>> = _allEvents

    init {
        repository= EventRepository().getInstance()
        repository.loadEvents(_allEvents)
    }
}

Repository

class EventRepository {

    private val databaseReference: DatabaseReference= FirebaseDatabase.getInstance().getReference("PetEvents")

    @Volatile private var INSTANCE : EventRepository ?=null

    fun getInstance() : EventRepository{
        return INSTANCE ?: synchronized(this) {
            val instance = EventRepository()
            INSTANCE=instance
            instance
        }
    }

    fun loadEvents(eventList : MutableLiveData<List<Event>>){

        databaseReference.addValueEventListener(object:ValueEventListener{
            override fun onDataChange(snapshot: DataSnapshot) {
                try {
                    val _eventList : List<Event> = snapshot.children.map { dataSnapshot ->
                        dataSnapshot.getValue(Event::class.java)!!
                    }
                    eventList.postValue(_eventList)
                }
                catch (e: Exception){
                    
                }
            }

            override fun onCancelled(error: DatabaseError) {
                TODO("Not yet implemented")
            }
        })
    }
}

Adapter

class EventAdapter : RecyclerView.Adapter<EventAdapter.MyViewHolder>() {

    private var eventList =ArrayList<Event>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
       val itemView = LayoutInflater.from(parent.context).inflate(
           R.layout.event_item_cell,
           parent, false
       )
        return MyViewHolder(itemView)
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val currentItem = eventList[position]
        holder.eventName.text =currentItem.eventName
        holder.eventTime.text =currentItem.eventTime
    }

    override fun getItemCount(): Int {
        return eventList.size
    }

    fun updateEventList(eventList: List<Event>){
        this.eventList.clear()
        this.eventList.addAll(eventList)
        notifyDataSetChanged()
    }

    class MyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
        val eventName :TextView = itemView.findViewById(R.id.txEventName)
        val eventTime :TextView = itemView.findViewById(R.id.txEventTime)
    }
}

展示数据的Fragment

private lateinit var viewModel : EventViewModel
private lateinit var eventRecyclerView: RecyclerView
lateinit var adapter: EventAdapter

class MainFragment : Fragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_main, container, false)
    }

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

        eventRecyclerView=view.findViewById(R.id.recyclerView)
        eventRecyclerView.layoutManager= LinearLayoutManager(context)
        eventRecyclerView.setHasFixedSize(true)
        adapter = EventAdapter()
        eventRecyclerView.adapter= adapter

        viewModel = ViewModelProvider(this).get(EventViewModel::class.java)

        viewModel.allEvents.observe(viewLifecycleOwner, Observer {
            adapter.updateEventList(it)
        })
    }
}

备注:Fragment布局已添加RecyclerView,Item布局为CardView,不确定是否影响结果。

排查与修复步骤

  1. 添加错误日志定位问题
    在Repository的onDataChange的catch块和onCancelled方法中添加日志打印,明确是数据读取失败还是解析出错:

    // onDataChange的catch块
    catch (e: Exception){
        Log.e("EventRepository", "数据解析失败", e)
    }
    
    // onCancelled方法实现
    override fun onCancelled(error: DatabaseError) {
        Log.e("EventRepository", "数据库读取取消", error.toException())
    }
    
  2. 检查Firebase数据库规则
    确保数据库规则允许读取操作,若未做用户认证,可临时调整规则为:

    {
      "rules": {
        ".read": true,
        ".write": true
      }
    }
    

    注意:上线前需修改为符合安全要求的规则。

  3. 修复数据类序列化问题
    Firebase解析数据需要无参构造函数,给Event类添加无参构造:

    data class Event(var eventName: String, var eventTime:String?=null){
        constructor() : this("")
    }
    

    或者给eventName设置默认值:

    data class Event(var eventName: String = "", var eventTime:String?=null)
    
  4. 修正Repository单例实现
    当前单例调用方式错误,ViewModel中初始化代码需改为:

    init {
        repository= EventRepository.getInstance()
        repository.loadEvents(_allEvents)
    }
    

    同时将Repository构造函数设为私有,避免外部直接实例化:

    private constructor()
    
  5. 验证RecyclerView及Item布局

    • 确保fragment_main中RecyclerView的宽高为match_parent,避免因布局尺寸问题导致内容不可见。
    • 检查event_item_cell中TextView的文字颜色与背景色有反差,且宽高设置合理。
  6. 确认LiveData数据更新
    在Fragment的Observer中添加日志,验证是否收到数据:

    viewModel.allEvents.observe(viewLifecycleOwner, Observer {
        Log.d("MainFragment", "收到数据条数:${it.size}")
        adapter.updateEventList(it)
    })
    

内容的提问来源于stack exchange,提问作者sueda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 18:20:26