RecycleView与ListView的区别以及RecycleView缓存机制总结

RV和LV的区别

LV:
  1. 继承并重写BaseAdapter类,布局效果单一
  2. 自定义ViewHolder和convertView的复用优化
  3. 可以通过addHeaderView()和addFooterView()添加下拉刷新的头部view与上拉加载更多的底部view,且不会影响Adapter的编写
  4. 在刷新条目数据时通常使用notifyDataSetChanged()方法这种刷新数据是全局刷新的方式,每个item的数据都会重新加载一遍,会消耗更多的资源,如果要实现局部刷新,则需要在Adapter中自定义方法,调用getFirstVisiblePosition()获取到对应item的position,然后调用getView()方法来刷新这个item的数据
  5. 没有动画效果的实现,需要自己在Adapter中自己实现
  6. 有现成的点击方法->onItemClickListener()->onItemLongClickListener()-onItemSelectedListener()
  7. 没有嵌套滚动机制
RV:
  1. 继承重写RecyclerView.Adapter类,覆写onCreateViewHolder方法和onBindViewHolder方法,实现自己的ViewHolder类,继承重写RecyclerView.Holder,通过设置LayoutManager以及layout的布局效果:线性,表格,瀑布流或者自定义LayoutManager
  2. 复用优化有四级缓存,无需自定义,如果不满足于默认设置,可以手动设置pool等缓存优化
  3. 没有添加HeaderView和FooterView的方法,需要在Adapter中根据getItemViewType()自己实现,但是这样会导致实际position的值产生偏差
  4. RecyclerView可以使用全局刷新和局部刷新->notifyItemChanged(int position)
  5. 有已经封装好的简单动画->notifyItemChange(),notifyDataInserted(),notifyItemMoved等,如需自定义动画,需要实现动画接口RecyclerView.ItemAnimator类,然后调用RecyclerView.setItemAnimator()设置动画效果
  6. 没有现成的点击事件,需要自己手动实现
  7. 实现了嵌套滑动机制.Android的事件分发机制中,Touch事件在进行分发时,有父View向子View传递,一旦子View消费了此事件则父View不在接受后续的分发处理,处理交由子View进行;但是嵌套滚动机制通过实现NestedScrollingChild()和NestedScrollingParent()两个接口可以让子View和父View同时处理此Touch事件

RV的四级缓存

  1. Scrap:一级缓存,缓存了屏幕内显示的所有viewholder,在这一级缓存的viewholder可以有效的避免重复的create和bind,缓存的时机是onLayout,并且用完后立即清空;在列表滑出新的item时,LayoutManager会先把屏幕中的所有的viewholder废弃掉,放入mAttachedView中,然后再根据flag重新布局每个itemview,并清空ScrapView
    1. mAttachedScrap,ArrayList,用于存放当前屏幕中的viewholder;用于存放flag为失效,移除的viewholder和完全没有改变的viewholder,有多少存多少;从这里获得的viewholder不需要走onBindViewHolder()方法
    2. mChangedScrap,ArrayList,用于存放数据被更新后的viewholder,也就是flag为更新的viewholder;这些viewholder需要被adapter重新绑定
  2. mCachedViwe,默认大小为2,用于存放预读取的viewholder,只有当所需的viewholder和position相同并且flag为有效时才获取此viewhodler,由于已经判断了viewholder是有效的,所以就不需要进行bind操作了;由于mCacheedView是有大小限制的,因此,如果超过了默认缓存大小,则会移除mCachedViwe的第一个viewholder,然后把需要添加的viewholder添加进入mCachedViwe,被移除的和不能加入的viewholder则会加入到mRecyclerViewPool中
  3. ViewCacheExtension,自定义缓存,通常用不到
  4. RecyclerViewPool,缓存池,根据viewType来缓存viewHolder,每个viewType可缓存的数量为5,可以动态的改变

RV的flag种类:失效,废弃,分离,移除,绑定,更新

缓存流程

RV复用的流程就是获取viewholder的流程;获取viewholder从Recycler的getViewForPosition开始

  1. 在mAttachedScrap或者mChangedScrap中根据position和flag查找到对应viewholder,获取并返回viewholder,根据flag决定viewhodler是否重新绑定
  2. 如果上一步没有获取到viewhodler,则从mCacheViews中匹配position获取viewholder缓存,获取并返回viewholder
  3. 如果上一步没有获取到viewhodler,则从ViewCacheExtension中获取viewholder,获取并返回viewholder
  4. 如果上一步没有获取到viewhodler,则从RecyclerViewPool中根据itemtype获取缓存的viewhodler,清除获取的viewhodler的所有标记位置,确保viewhodler能重新被adapter绑定
  5. 如果上一步没有获取到viewhodler,则走adapter的CreateViewHolder方法,创建一个新的viewholder,并经过adapter的bindViewHolder绑定改viewholder

源码分析干货:
https://www.jianshu.com/p/c52b947fe064
https://www.jianshu.com/p/efe81969f69d
https://juejin.im/post/5b79a0b851882542b13d204b

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章