垂直RecyclerView滚动卡顿,是否应替换为ListView?
结论:绝对不建议将外层RecyclerView替换为ListView
ListView早已被Android官方弃用,它缺乏RecyclerView的视图复用、灵活布局、DiffUtil高效更新等核心优化特性,牺牲加载速度也无法从根本解决滚动卡顿问题,反而会引入兼容性和维护隐患。针对你嵌套RecyclerView的滚动卡顿问题,通过以下针对性优化即可解决:
核心优化方案
1. 避免重复创建Adapter与LayoutManager
你当前在LoadDataHome中每次获取数据都会新建Adapter和LayoutManager,这会触发大量不必要的视图重建。改为复用已有实例:
// HomeFragment中声明成员变量 private lateinit var adapterPrincipal: HomeResponseAdapter override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding = FragmentHomeBinding.bind(view) // 初始化一次Adapter和LayoutManager adapterPrincipal = HomeResponseAdapter(mutableListOf()) binding.rvPrincipal.apply { layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) adapter = adapterPrincipal setHasFixedSize(true) // 固定RecyclerView尺寸,减少重复布局计算 } // 数据观察逻辑不变,仅修改数据更新方式 viewModel.fetchDataInicio().observe(viewLifecycleOwner) { result -> when (result) { is Resource.Loading -> Log.d("LiveDataFetchDataInicio", "Loading") is Resource.Success -> adapterPrincipal.updateData(result.data) is Resource.Failure -> Log.d("ErrorFetchDataInicio", "${result.exception}") } } }
在HomeResponseAdapter中添加数据更新方法:
fun updateData(newList: List<HomeResponseItem>) { itemList.clear() itemList.addAll(newList) notifyDataSetChanged() }
2. 替换为ListAdapter实现高效数据更新
使用ListAdapter结合DiffUtil,仅更新数据变化的项,避免全局视图刷新:
class HomeResponseAdapter : ListAdapter<HomeResponseItem, RecyclerView.ViewHolder>(DiffCallback()) { companion object { private class DiffCallback : DiffUtil.ItemCallback<HomeResponseItem>() { override fun areItemsTheSame(oldItem: HomeResponseItem, newItem: HomeResponseItem): Boolean { return oldItem.idContenido == newItem.idContenido // 用唯一标识判断项是否相同 } override fun areContentsTheSame(oldItem: HomeResponseItem, newItem: HomeResponseItem): Boolean { return oldItem == newItem // 数据类可直接比较,非数据类需手动对比字段 } } } // 其余onCreateViewHolder、onBindViewHolder逻辑不变,仅将itemList[position]替换为getItem(position) override fun getItemCount(): Int = currentList.size }
此时数据更新只需调用:
adapterPrincipal.submitList(result.data)
3. 优化子水平RecyclerView性能
- 关闭嵌套滚动:每个子RecyclerView添加
setNestedScrollingEnabled(false),让外层RecyclerView统一处理滚动逻辑,减少绘制冲突 - 复用子Adapter与LayoutManager:在ViewHolder初始化时创建子Adapter和LayoutManager,避免每次bind时重复创建
示例ViewHolder代码:
class PillButtonCarouselViewHolder(view: View) : RecyclerView.ViewHolder(view) { private val rvPillButtons = view.findViewById<RecyclerView>(R.id.rv_pill_buttons) private val adapter = PillButtonAdapter() init { rvPillButtons.apply { layoutManager = LinearLayoutManager(itemView.context, LinearLayoutManager.HORIZONTAL, false) adapter = this@PillButtonCarouselViewHolder.adapter setNestedScrollingEnabled(false) // 关键:关闭嵌套滚动 } } fun bind(data: List<PillButton>) { adapter.submitList(data) // 子Adapter也建议用ListAdapter } }
4. 视图层级与绘制优化
- 检查所有item布局文件,用
ConstraintLayout替代嵌套的LinearLayout/RelativeLayout,减少布局层级 - 如果item包含图片,使用Glide/Coil等加载库进行压缩、缓存,避免大图片占用过多内存
- 确保应用开启硬件加速(默认开启,可在AndroidManifest.xml中确认)
内容的提问来源于stack exchange,提问作者Gregorio Scalbi
相关产品推荐
相关产品推荐

