RecyclerView性能优化及高级使用_潇潇凤儿的博客-CSDN博客_recyclerview优化方案
DiffUtil
,来进行局部数据刷新,而不是一味的全局刷新数据。DiffUtil
是support包下新增的一个工具类,用来判断新数据和旧数据的差别,从而进行局部刷新。DiffUtil的使用,在原来调用 mAdapter.notifyDataSetChanged()
的地方:
- // mAdapter.notifyDataSetChanged()
- DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffCallBack(oldDatas, newDatas), true);
- diffResult.dispatchUpdatesTo(mAdapter);
减少布局层级,可以考虑使用自定义View来减少层级,或者更合理的设置布局来减少层级。
onCreateViewHolder 和 onBindViewHolder 对时间都比较敏感,尽量避免繁琐的操作和循环创建对象。例如创建 OnClickListener,可以全局创建一个。同时onBindViewHolder调用次数会多于onCreateViewHolder的次数,如从RecyclerViewPool缓存池中取到的View都需要重新bindView,所以我们可以把监听放到CreateView中进行。
一个稍微复杂的 Item 会包含大量的 View,而大量的 View 的创建也会消耗大量时间,所以要尽可能简化 ItemView;设计 ItemType 时,对多 ViewType 能够共用的部分尽量设计成自定义 View,减少 View 的构造和嵌套。
如果item高度是固定的话,可以使用
RecyclerView.setHasFixedSize(true);
来避免requestLayout浪费资源。
设置
RecyclerView.addOnScrollListener();
来在滑动过程中停止加载的操作。
6.1 setItemViewCacheSize( int )
RecyclerView可以设置自己所需要的ViewHolder缓存数量,默认大小是2。cacheViews中的缓存只能position相同才可得用,且不会重新bindView,CacheViews满了后移除到RecyclerPool中,并重置ViewHolder,如果对于可能来回滑动的RecyclerView,把CacheViews的缓存数量设置大一些,可以减少bindView的时间,加快布局显示。
注:此方法是拿空间换时间,要充分考虑应用内存问题,根据应用实际使用情况设置大小。
网上大部分设置CacheView大小时都会带上:
setDrawingCacheEnabled(true)和setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH)
setDrawingCacheEnabled这个是View本身的方法,意途是开启缓存。通过setDrawingCacheEnabled把cache打开,再调用getDrawingCache就可以获得view的cache图片,如果cache没有建立,系统会自动调用buildDrawingCache方法来生成cache。一般截图会用到,这里的设置drawingcache,可能是在重绘时不需要重新计算bitmap的宽高等,能加快dispatchDraw的速度,但开启drawingcache,肯定也会耗应用的内存,所以也慎用。
6.2 复用RecycledViewPool
在TabLayout+ViewPager+RecyclerView的场景中,当多个RecyclerView有相同的item布局结构时,多个RecyclerView共用一个RecycledViewPool可以避免创建ViewHolder的开销,避免GC。RecycledViewPool对象可通过RecyclerView对象获取,也可以自己实现。
RecycledViewPool mPool = mRecyclerView1.getRecycledViewPool();
下一个RecyclerView可直接进行setRecycledViewPool
mRecyclerView2.setRecycledViewPool(mPool);
mRecyclerView3.setRecycledViewPool(mPool);
注意:
(1)RecycledViewPool是依据ItemViewType来索引ViewHolder的,必须确保共享的RecyclerView的Adapter是同一个,或view type 是不会冲突的。
(2)RecycledViewPool可以自主控制需要缓存的ViewHolder数量,每种type的默认容量是5,可通过setMaxRecycledViews来设置大小。mPool.setMaxRecycledViews(itemViewType, number); 但这会增大应用内存开销,所以也需要根据应用具体情况来使用。
(3)利用此特性一般建议设置layout.setRecycleChildrenOnDetach(true);此属性是用来告诉LayoutManager从RecyclerView分离时,是否要回收所有的item,如果项目中复用RecycledViewPool时,开启该功能会更好的实现复用。其他RecyclerView可以复用这些回收的item。
什么时候LayoutManager会从RecyclerView上分离呢,有两种情况:1)重新setLayoutManager()时,比如淘宝页面查看商品列表,可以线性查看,也可以表格形式查看,2)还有一种是RecyclerView从视图树上被remove时。但第一种情况,RecyclerView内部做了回收工作,设不设置影响不大,设置此属性作用主要针对第二种情况。