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

垂直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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 12:54:53