之前有总结过ListView的缓存机制和RecyclerView的缓存机制,那这两种到底有什么区别呢

简单了解下缓存的基本原理

1)在初始化onLayout过程中,都有一个 mAttachedxxx的集合,临时存在即将显示的第一屏的view,在最后一次onLayout结束之后,会从将该mAttachedxxx里面的view渲染到第一屏页面上。

2)当向上滑动过程中,都是先将滑出屏幕的view放到Recycle中,然后从Recycle中经过转换,将该view渲染到界面上。只是在缓存处理和缓存的内容上有点区别。

3)在数据源发生变化的时候,xxxxxxxxxx

发现缓存机制的层级数差别

ListView和RecyclerView的缓存层级数不同,RecyclerView支持开发者自定义缓存逻辑,支持RecyclerViewPool缓存池,同时支持多个RecyclerView共用该RecyclerViewPool。

ListView(两级缓存)

缓存集合

是否需要重新创建view

是否需要重新设置view数据

作用域

集合元素变化

mActiveViews

否,直接将第一次onLayout创建的view添加到该集合中

否,因为就是第一屏的view重新渲染到ListView中

add:发生在每次onLayout或初始化的第二次onLayout;

每次onLayout的当前view集合

clear:从集合中取出该元素,则马上将该集合中的元素置为null

mScrapViews

否,将正在显示的view添加到该集合中,

是,需要重新调用getView去绑定数据,因为不同position在复用该view时,对应该位置的数据源是不一致的,通常我们只会去用该view,而重新设置数据

add:显示另外一屏view时;

1)若数据源没有发生变化始终为第一屏的view集合;

2)若数据源发生变化,会将所有的view都加入到该集合中

3)若adapter发生变化,该集合中的view才会发生变化

clear:与adapter保持一致,只有当adapter数据发生变化的时候,即调用setAdapter的时候,才会清空该集合中的元素

RecylerView(四级缓存)

缓存集合

是否需要重新创建view

是否需要重新设置view数据

作用域

集合元素变化

mAttachedView



add:发生在每次onLayout或初始化的第二次onLayout;

 

clear:

mCacheViews

 

否,默认的保存的两个view和view的数据

否,默认的保存的两个view和view的数据,因为保存的就是对应position的view和数据,只要位置对了才可以使用

add:显示另一屏的view时,会将移除屏幕的view添加到该集合中,最大容量为可以设置,默认为2

不同的LayoutManager缓存的holder集合元素不一致,在变化中,默认的2个

clear:当超出最大容量时,只会移除一个元素;

清除所有元素:与adapter保持一致,只有当adapter数据发生变化的时候,即调用setAdapter的时候,也会清空该集合中的元素。

mViewCacheExtension

 

 

不直接使用,需要开发者定义

 

mRecyclerPool

否,缓存view,但数据不缓存

是,需要重新执行onBindViewHolder去重新设置数据

add:将mCacheViews集合中的个数超过设置的值(默认为2)时,则将mCacheViews里面的元素add到该集合中

元素发生变化,默认的不同类型的viewType对应的为5个

同时可以实现多个RecyclerView共用一个ViewPool

clear:

从上面的表格对比中可以看出:

RecyclerView在缓存层级上,只是多了一个mCacheViews,可以保证屏幕外的view在进入到屏幕时无须进行绑定数据,但是这里也必须是对应position的view才可以复用

发现缓存内容的不同

 

缓存内容

缓存之后的复用

缓存和复用的顺序

ListView

View,需要每次都要绑定数据

需要缓存的时候,将当前屏幕的所有view都添加到二级缓存mScrapViews,在复用的时候全都需要bindView

先缓存在复用,所以在数据没有发生变化的前提下,第二屏数据就可以复用缓存的view;

即使数据发生变化,在加载的view,也是可以直接复用view

RecyclerView

RecyclerView.ViewHolder=View+ViewHolder(findViewById)+flag,有的时候可以直接拿来使用,有的时候仅仅需要绑定数据就可以了

需要缓存的时候,会根据mCacheViews和mRecyclerPool里的个数和顺序依次添加,用来区分加入的view是否需要重新bindView

先复用在缓存,所以在数据没有发生变化的前提下,如果显示第二屏的view,仍要从create-bind,直到第三屏的view才可使用缓存的view。

下面用流程图来简单的说明下缓存过程

ListView的缓存流程

android listview 设置缓存数量 listview缓存机制_Android

RecyclerView的缓存流程

缓存流程和ListView差不多,只不过调用的方法名不同,多了两层缓存,可以参见RecyclerView的Recycler

总结

像平常的简单列表展示静态view的时候,其实我觉得ListView和RecyclerView没有太多区别,但是RecyclerView的优势在于:

1)局部刷新,减少调用bindView

2)频繁更新数据源和view的显示的内容

3)支持Item的动画

4)支持多种列表,像普通的列表、网格、瀑布流