RecyclerView缓存机制
Posted Zhang Jun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RecyclerView缓存机制相关的知识,希望对你有一定的参考价值。
RecyclerView分为四级缓存
RecyclerView根据不同的状态可以分为:屏幕内缓存、屏幕外缓存、自定义缓存、缓存池。RecyclerView是通过内部类Recycler来管理缓存。
一级缓存:屏幕内缓存(mAttachedScrap)
屏幕内缓存指在屏幕中显示的ViewHolder,这些ViewHolder会缓存在mAttachedScrap、mChangedScrap中 :
-
mChangedScrap 表示数据已经改变的ViewHolder列表,需要重新绑定数据(调用onBindViewHolder)
-
mAttachedScrap 未与RecyclerView分离的ViewHolder列表
二级缓存:屏幕外缓存(mCachedViews)
用来缓存移除屏幕之外的 ViewHolder,默认情况下缓存容量是 2,可以通过 setViewCacheSize 方法来改变缓存的容量大小。如果 mCachedViews 的容量已满,则会优先移除旧 ViewHolder,把旧ViewHolder移入到缓存池RecycledViewPool 中。
三级缓存:自定义缓存(ViewCacheExtension)
给用户的自定义扩展缓存,需要用户自己管理 View 的创建和缓存,可通过Recyclerview.setViewCacheExtension()设置。
四级缓存:缓存池(RecycledViewPool )
ViewHolder 缓存池,在mCachedViews中如果缓存已满的时候(默认最大值为2个),先把mCachedViews中旧的ViewHolder 存入到RecyclerViewPool。如果RecyclerViewPool缓存池已满,就不会再缓存。从缓存池中取出的ViewHolder ,需要重新调用bindViewHolder绑定数据。
- 按照 ViewType 来查找 ViewHolder
- 每个 ViewType 默认最多缓存 5 个
- 可以多个 RecyclerView 共享 RecycledViewPool
RecyclerViewPool底层是使用了SparseArray来分开存储不同ViewType的ViewHolder集合
缓存策略
Recyclerview在获取ViewHolder时按四级缓存的顺序查找,如果没找到就创建。其中只有RecycledViewPool找到时才会调用 onBindViewHolder,其它缓存不会重新bindViewHolder 。 流程如下 :
RecyclerView优化
-
降低item的布局层次
降低item布局层级,可以减少界面创建的渲染时间,使用约束布局等。 -
去除冗余的setOnItemClick事件
直接在onBindViewHolder方法中创建一个匿名内部类的方式来实现setOnItemClick是不可取的,这会导致在RecyclerView快速滑动时创建很多对象,优化方法为:事件的绑定和viewholder对应的rootView进行绑定 -
复用pool缓存
如果存在RecyclerView中嵌套RecyclerView的情况,可以考虑复用RecyclerViewPool缓存池,减少开销。
总结
通过了解RecyclerView的四级缓存,我们可以知道,RecyclerView最多可以缓存 N(屏幕最多可显示的item数) + 2 (屏幕外的缓存) + 5*M (M代表M个ViewType,缓存池的缓存),只有RecycledViewPool找到时才会重新调用 onBindViewHolder。
附注
ViewHolder
-
ViewHolder的主要任务:容纳View视图。
-
Adapter
Adapter从模型层获取数据,然后提供给RecyclerView显示,是沟通的桥梁。Adapter主要的任务是:创建ViewHolder和将模型层的数据绑定到ViewHolder上。 -
提升ListView的运行效率
两个方面提高效率,加载布局的效率和初始化实例的效率-
Adapter中的getView方法修改:如果convertView为null,使用LayoutInflater去加载布局;不为null,则直接对convertView进行重用。
-
内部类ViewHolder,实现对数据的缓冲。当convertView为null时,创建ViewHolder实例,将控件的实例都存放在ViewHolder中,调用View的setTag()方法,将ViewHolder的对象存储在View中。当convertView不为null时,调用view的getTag()方法,把ViewHolder重新取出。
-
以上是关于RecyclerView缓存机制的主要内容,如果未能解决你的问题,请参考以下文章