这是我参与「第四届青训营 」笔记创作活动的第8天
RecyclerView的缓存机制
一、RecyclerView强制我们使用的ViwHolder模式
1、ListView不强制实现ViewHolder,但是Google建议实现
两种不同的模式
- 不使用ViewHolder的模式
- 使用ViewHolder的模式
对比发现ListView使用ViewHolder的好处就是可以避免每次getView都进行findViewById()操作,findViewById()使用的是DFS算法(深度优先查找),非常耗费性能。而对于RecyclerView来说,强制实现ViewHolder的其中一个原因就是避免多次进行findViewById()的处理,另一个原因就是因为ItemView和ViewHolder的关系是一对一,也就是说一个ViewHolder对应一个ItemView。这个ViewHolder当中持有对应的ItemView的所有信息,比如说:position;view;width等等,拿到了ViewHolder基本就拿到了ItemView的所有信息,而ViewHolder使用起来相比itemView更加方便。RecyclerView缓存机制缓存的就是ViewHolder(ListView缓存的是ItemView),这也是为什么RecyclerView为什么强制我们实现ViewHolder的原因
二、ListView的缓存机制
ListView的缓存有两级,在ListView内部有一个内部类RecyclerBin,RecyclerBin有两个对象Active View和Scrap View来管理缓存,Active View是第一级,Scrap View是第二级
- Active View:是缓存在屏幕内的ItemView,当列表数据发送变化时,屏幕内数据可以直接拿来复用,无需进行数据绑定
- Scarp View:缓存屏幕外的ItemView,这里所有的缓存的数据都是"脏的",也就是数据需要重新绑定,也就是说屏幕外的所有数据在进入屏幕的时候都要走一遍getView()方法
- ListView的缓存流程:
- 当Active View和Scrap View中都没有缓存的时候就会直接create view
小结:ListView的缓存机制只有两级缓存,一级缓存Active View是负责屏幕内的ItemView快速复用,而Scrap View是缓存屏幕外的数据,当该数据从屏幕外滑动到屏幕内的时候需要走一遍getView()方法
三、RecyclerView的缓存机制
1、RecyclerView的缓存分为四级
- Scrap(废料、残余物):对应ListView 的Active View,就是屏幕内的缓存数据,可以直接拿来复用。
- Cache:刚刚移出屏幕的缓存数据,默认大小是2个,当其容量被充满同时又有新的数据添加的时候,会根据FIFO原则(先进先出),把优先进入的缓存数据移出并放到下一级缓存中,然后再把新的数据添加进来。Cache里面的数据是干净的,也就是携带了原来的ViewHolder的所有数据信息,数据可以直接来拿来复用。需要注意的是,cache是根据position来寻找数据的,这个postion是根据第一个或者最后一个可见的item的position以及用户操作行为(上拉还是下拉)。 举个栗子:当前屏幕内第一个可见的item的position是1,用户进行了一个下拉操作,那么当前预测的position就相当于(1-1=0),也就是position=0的那个item要被拉回到屏幕,此时RecyclerView就从Cache里面找position=0的数据,如果找到了就直接拿来复用
- ViewCacheExtension:google留给开发者自己来自定义缓存的
- RecyclerViewPool:因为第二级缓存Cache默认的缓存数量是2个,当Cache缓存满了以后会根据FIFO(先进先出)的规则把Cache先缓存进去的ViewHolder移出并缓存到RecycledViewPool中,RecycledViewPool默认的缓存数量是5个。RecycledViewPool与Cache相比不同的是,从Cache里面移出的ViewHolder再存入RecycledViewPool之前ViewHolder的数据会被全部重置,相当于一个新的ViewHolder,而且Cache是根据position来获取ViewHolder,而RecycledViewPool是根据itemType获取的,如果没有重写getItemType()方法,itemType就是默认的。因为RecycledViewPool缓存的ViewHolder是全新的,所以取出来的时候需要走onBindViewHolder()方法
小结:ListView有两级缓存,分别是Active View和Scrap View,缓存的对象是ItemView;而RecyclerView有四级缓存,分别是Scrap、Cache、ViewCacheExtension和RecycledViewPool,缓存的对象是ViewHolder。Scrap和Cache分别是通过position去找ViewHolder可以直接复用;ViewCacheExtension自定义缓存,目前来说应用场景比较少却需慎用;RecycledViewPool通过type来获取ViewHolder,获取的ViewHolder是个全新,需要重新绑定数据,可以避免用户调用onCreateViewHolder()方法,提高性能,在ViewPager+RecyclerView的应用场景下可以大有作为