浅谈RecyclerView的性能优化

813次阅读  |  发布于1年以前

RecyclerView的性能优化

相信大家在平时开发的过程中都会遇到RecyclerView卡顿的情况,那么如何才能够让RecyclerView变得更加丝滑呢?今天我就来和大家浅谈RecyclerView的性能优化.

RecyclerView缓存机制

在我们谈RecyclerView的性能优化之前,先让我们回顾一下RecyclerView的缓存机制。

众所周知,RecyclerView拥有四级缓存,它们分别是:

RecyclerView的回收原理

(1)如果是RecyclerView不滚动情况下缓存(比如删除item)、重新布局时。

(2)如果是RecyclerView滚动情况下缓存(比如滑动列表),在滑动时填充布局。

RecyclerView的复用原理

当RecyclerView要拿一个复用的ViewHolder时:

这里有几点需要注意:

缓存机制总结

如果想深入了解RecyclerView缓存机制的同学,可以参考《RecyclerView的回收复用缓存机制详解》 这篇文章。

性能优化方案

根据上面我们对缓存机制的了解,我们可以简单得到以下几个大方向:

提高ViewHolder的复用

1.多使用Scrap进行局部更新。

 @Override
public void onBindViewHolder(@NonNull RecyclerViewHolder holder, int position, @NonNull List<Object> payloads) {
    if (CollectionUtils.isEmpty(payloads)) {
        Logger.e("正在进行全量刷新:" + position);
        onBindViewHolder(holder, position);
        return;
    }
    // payloads为非空的情况,进行局部刷新
    //取出我们在getChangePayload()方法返回的bundle
    Bundle payload = WidgetUtils.getChangePayload(payloads);
    if (payload == null) {
        return;
    }
    Logger.e("正在进行增量刷新:" + position);
    for (String key : payload.keySet()) {
        if (KEY_SELECT_STATUS.equals(key)) {
            holder.checked(R.id.scb_select, payload.getBoolean(key));
        }
    }
}

详细使用方法可参考XUI中的RecyclerView局部增量刷新 中的代码。

详细使用方法可参考XUI中的DiffUtil局部刷新 和 XUI中的SortedList自动数据排序刷新 中的代码。

2.合理设置RecyclerViewPool的大小。如果一屏的item较多,那么RecyclerViewPool的大小就不能再使用默认的5,可适度增大Pool池的大小。如果存在RecyclerView中嵌套RecyclerView的情况,可以考虑复用RecyclerViewPool缓存池,减少开销。

3.为RecyclerView设置setHasStableIds为true,并同时重写RecyclerView.Adapter的getItemId方法来给每个Item一个唯一的ID,提高缓存的复用率。

4.视情况使用setItemViewCacheSize(size)来加大CacheView缓存数目,用空间换取时间提高流畅度。对于可能来回滑动的RecyclerView,把CacheViews的缓存数量设置大一些,可以省去ViewHolder绑定的时间,加快布局显示。

5.当两个数据源大部分相似时,使用swapAdapter代替setAdapter。这是因为setAdapter会直接清空RecyclerView上的所有缓存,但是swapAdapter会将RecyclerView上的ViewHolder保存到pool中,这样当数据源相似时,就可以提高缓存的复用率。

优化onBindViewHolder方法

1.在onBindViewHolder方法中,去除冗余的setOnItemClick等事件。因为直接在onBindViewHolder方法中创建匿名内部类的方式来实现setOnItemClick,会导致在RecyclerView快速滑动时创建很多对象。应当把事件的绑定在ViewHolder创建的时候和对应的rootView进行绑定。

2.数据处理与视图绑定分离,去除onBindViewHolder方法里面的耗时操作,只做纯粹的数据绑定操作。当程序走到onBindViewHolder方法时,数据应当是准备完备的,禁止在onBindViewHolder方法里面进行数据获取的操作。

3.有大量图片时,滚动时停止加载图片,停止后再去加载图片。

4.对于固定尺寸的item,可以使用setHasFixedSize避免requestLayout

优化onCreateViewHolder方法

1.降低item的布局层级,可以减少界面创建的渲染时间。

2.Prefetch预取。如果你使用的是嵌套的RecyclerView,或者你自己写LayoutManager,则需要自己实现Prefetch,重写collectAdjacentPrefetchPositions方法。

其他

以上都是针对RecyclerView的缓存机制展开的优化方案,其实还有几种方案可供参考。

1.取消不需要的item动画。具体的做法是:

((SimpleItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);

2.使用getExtraLayoutSpace为LayoutManager设置更多的预留空间。当RecyclerView的元素比较高,一屏只能显示一个元素的时候,第一次滑动到第二个元素会卡顿,这个时候就需要预留的额外空间,让RecyclerView预加载可重用的缓存。

最后

以上就是RecyclerView性能优化的全部内容,俗话说:百闻不如一见,百见不如一干,大家还是赶紧动手尝试着开始进行优化吧!

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8