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
相关产品推荐
相关产品推荐

