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

NavigationDrawer切换Fragment后RecyclerView的onCreateViewHolder与onBindViewHolder不调用

问题原因&解决方案

核心bug原因

你的Adapter存在两个数据源引用不同步的问题:

  • 初始状态下,你在FetchFragment中创建的personsList传给Adapter后,Adapter的persons(渲染用数据源)和personsList(过滤用原始数据源)都指向同一个列表对象,所以第一次加载可以正常渲染。
  • 只要你触发过一次搜索过滤操作,publishResults方法会将persons重新赋值为过滤后的新列表,此时persons就和Fragment中的personsList断开了引用关联。
  • 后续你在Fragment中更新自己的personsList、调用notifyDataSetChanged时,Adapter的persons还是指向旧的列表,getItemCount返回的始终是旧列表的长度(大多数情况是0),所以onCreateViewHolder和onBindViewHolder不会触发,RecyclerView自然没有内容。

另外还有两个潜在问题:

  • 如果你使用的NavigationDrawer切换逻辑是hide/show而不是replace,onViewCreated只会在Fragment第一次创建时执行一次,切回Fragment时不会重新拉取数据。
  • 你当前用的全局协程没有绑定Fragment生命周期,Fragment销毁后协程还在运行可能导致内存泄漏或空指针异常。

修复步骤

1. 给Adapter添加更新数据的统一方法

在PersonsAdapter中新增如下方法,保证更新数据时两个数据源同步:

fun updateData(newList: List<PersonsDb>) {
    persons = newList
    personsList = newList
    notifyDataSetChanged()
}

2. 修改Fragment中数据加载后的更新逻辑

把fetchPPerson方法中原来的adapter.notifyDataSetChanged()替换为调用上面新增的updateData方法,同时优化协程写法绑定生命周期:

// 把原来的CoroutineScope改成viewLifecycleOwner.lifecycleScope
private fun fetchPPerson() = viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
    try {
        val querySnapshot = personCollectionRef.get().await()
        val newList = mutableListOf<PersonsDb>() // 直接创建新列表避免引用问题
        for (document in querySnapshot.documents) {
            val person = document.toObject<Person>()
            newList.add(
                PersonsDb(
                    document.id,
                    person?.name.toString(),
                    person?.age.toString().toInt(),
                    Date(person?.dob.toString())
                )
            )
        }
        withContext(Dispatchers.Main) {
            adapter.updateData(newList) // 调用统一更新方法
        }
    } catch (e: Exception) {
        withContext(Dispatchers.Main) {
            Toast.makeText(requireContext(), e.message, Toast.LENGTH_LONG).show()
            Log.d("Fetch Error", e.message)
        }
    }
}

3. 适配Fragment生命周期(可选,针对hide/show切换场景)

如果你的Navigation切换用的是hide/show逻辑,就把fetchPPerson的调用从onViewCreated移到onResume中,保证每次Fragment切到前台都会拉取最新数据:

override fun onResume() {
    super.onResume()
    fetchPPerson()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.20 03:15:04