目录

RecyclerView / ListView

RecyclerView / ListView

区别

  1. ListView 布局单一, RecyclerView 有横向纵向瀑布流表格等布局
  2. ListView 需要实现 ArrayAdapter, RecyclerView 则是 RecyclerView.Adapter<ViewHolder>
  3. ListView 缓存 View, 离屏缓存, 从 mScrapViews 根据 pos 获取相应的缓存 getView 之后进行 bindView RecyclerView 则是通过缓存 ViewHolder 实现了重用无需 bindView()
  4. RecyclerView 支持局部刷新

缓存机制

RecyclerView
  • mAttachedScrap: 第一级缓存, 相当于 ListView 的 mActiveView, 快速重用屏幕上可见的 ViewHolder

  • mCacheViews: 第二级缓存, 默认缓存 2 个 ItemView, RecycleView 从这里获取的缓存时, 如果数据源不变的情况下, 无需重新 bindView

  • mViewCacheExtension: 第三级缓存, 需要开发者实现

  • RecycledViewPool : 通过SparseArray<ArrayList<ViewHolder>> 通过 SparseArray 实现的轻量 Map, 根据不同的 itemType 使用不同的缓存

RecyclerView 优化

  • 分离视图绑定和数据处理
    • 尽量只在 onBindViewHolder 中只设置数据, 数据应该在 onBindViewHolder 之前计算好
  • 分页延迟加载, 比如说使用 Paging 组件
  • 减少 View 层级
  • 加大 RecyclerView.mCachedViews的缓存
  • 共享 RecycledViewPool
    • RecyclerView.setRecycledViewPool(): 前提是子项 RecycleView 的 Adapter 是相同的
  • 局部刷新
    • notifyDataSetChanged()全部刷新
    • notifyItemChanged (int)指定一个刷新
    • notifyItemRangeChanged(int, int)指定刷新起始 个数
    • notifyItemInserted(int) 插入一个并刷新
    • notifyItemRemoved(int)移除一个并刷新

和 ScrollView 冲突

出现场景: 为了偷懒, 给 RecyclerView 设置 header 直接使用了ScrollView 里面嵌套了 header 和一个 RecyclerView

解决方案:

  1. NestedScrollView + recyclerView.isNestedScrollingEnabled = false
  2. 不用scrollView, recyclerView 设置多种 itemType
  3. 如果滑动方向不同, 可以考虑重写recyclerView 的 LinearLayoutManager->canScrollVertically 为false之类的方法