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

Android中RecyclerView除第一项外其余项显示为空的问题

解决RecyclerView除第一项外均显示默认文本的问题

我一眼就看到你代码里的问题啦——核心出在ViewHolder的控件引用方式上,再加上一些小细节需要调整。咱们一步步来搞定:

核心问题:控件引用未正确缓存/绑定

你在ViewHolder的bind方法里直接用name_customer?.text,如果你的项目没有启用kotlin-android-extensions(这个插件现在已经被官方废弃),那这个name_customer其实是null!为什么第一项能显示?大概率是第一次创建ViewHolder时,刚好通过视图层级临时找到了这个控件,但RecyclerView复用ViewHolder的时候,就无法正确获取控件引用了,所以只能显示布局里的默认文本"test"。

另外还有个小细节:设置Adapter的顺序可以调整下,先设置LayoutManager再设置Adapter,能避免RecyclerView初始化时的潜在异常。

修复方案(推荐用View Binding,更安全可靠)

第一步:启用View Binding

在你的app模块的build.gradle(或build.gradle.kts)里开启View Binding功能:

android {
    ...
    buildFeatures {
        viewBinding true
    }
}

第二步:修改Adapter和ViewHolder

改用View Binding来绑定列表项视图,确保控件引用永远不为null:

inner class CustomerAdapterTest(private var items: List<Customer>) : RecyclerView.Adapter<CustomerAdapterTest.ViewHolder>() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        // 用View Binding加载列表项布局
        val binding = ItemCustomerTestBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(items[position])

    override fun getItemCount() = items.size

    // ViewHolder持有Binding实例,避免重复查找控件
    inner class ViewHolder(private val binding: ItemCustomerTestBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bind(item: Customer) {
            // 通过Binding直接设置文本
            binding.nameCustomer.text = item.name
        }
    }
}

第三步:调整Fragment里的初始化顺序

把LayoutManager的设置移到Adapter之前,让RecyclerView先明确布局规则:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    // 添加数据...

    rv_list_customers.layoutManager = LinearLayoutManager(context) // 先设置LayoutManager
    val adapter = CustomerAdapterTest(customers)
    rv_list_customers.adapter = adapter
    // 初始化时已经传入数据,不需要额外调用notifyDataSetChanged
    // adapter.notifyDataSetChanged() 
}

备用方案(不用View Binding,手动缓存控件)

如果你暂时不想用View Binding,那就在ViewHolder里用findViewById提前缓存TextView:

inner class CustomerAdapterTest(private var items: List<Customer>) : RecyclerView.Adapter<CustomerAdapterTest.ViewHolder>() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder = ViewHolder(parent.inflate(R.layout.item_customer_test))

    override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bind(items[position])

    override fun getItemCount() = items.size

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        // 提前缓存TextView,避免每次bind都重新查找
        private val tvName = itemView.findViewById<TextView>(R.id.name_customer)
        
        fun bind(item: Customer) {
            tvName.text = item.name
        }
    }
}

这样修改后,RecyclerView的所有列表项都会正确显示你设置的名称文本啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:28:06