相信大家在平时开发的过程中都会遇到RecyclerView卡顿的情况,那么如何才能够让RecyclerView变得更加丝滑呢?今天我就来和大家浅谈RecyclerView的性能优化.
在我们谈RecyclerView的性能优化之前,先让我们回顾一下RecyclerView的缓存机制。
众所周知,RecyclerView拥有四级缓存,它们分别是:
Scrap缓存:包括mAttachedScrap和mChangedScrap,又称屏内缓存,不参与滑动时的回收复用,只是用作临时保存的变量。
mAttachedScrap:只保存重新布局时从RecyclerView分离的item的无效、未移除、未更新的holder。
mChangedScrap:只会负责保存重新布局时发生变化的item的无效、未移除的holder。
CacheView缓存:mCachedViews又称离屏缓存,用于保存最新被移除(remove)的ViewHolder,已经和RecyclerView分离的视图,这一级的缓存是有容量限制的,默认最大数量为2。
ViewCacheExtension:mViewCacheExtension又称拓展缓存,为开发者预留的缓存池,开发者可以自己拓展回收池,一般不会用到。
RecycledViewPool:终极的回收缓存池,真正存放着被标识废弃(其他池都不愿意回收)的ViewHolder的缓存池。这里的ViewHolder是已经被抹除数据的,没有任何绑定的痕迹,需要重新绑定数据。
(1)如果是RecyclerView不滚动情况下缓存(比如删除item)、重新布局时。
mCachedViews
> RecycledViewPool
的优先级缓存到mCachedViews或者RecycledViewPool中。(2)如果是RecyclerView滚动情况下缓存(比如滑动列表),在滑动时填充布局。
当RecyclerView要拿一个复用的ViewHolder时:
重新绑定数据
。createViewHolder()
重新去创建一个。这里有几点需要注意:
onBindViewHolder()
重新绑定数据才能使用。如果想深入了解RecyclerView缓存机制的同学,可以参考《RecyclerView的回收复用缓存机制详解》 这篇文章。
根据上面我们对缓存机制的了解,我们可以简单得到以下几个大方向:
onBindViewHolder
方法,减少ViewHolder绑定的时间。由于ViewHolder可能会进行多次绑定,所以在onBindViewHolder()
尽量只做简单的工作。onCreateViewHolder
方法,减少ViewHolder创建的时间。1.多使用Scrap进行局部更新。
notifyItemChange
、notifyItemInserted
、notifyItemMoved
和notifyItemRemoved
等方法替代notifyDataSetChanged
方法。notifyItemChanged(int position, @Nullable Object payload)
方法,传入需要刷新的内容进行局部增量刷新。这个方法一般很少有人知道,具体做法如下:RecyclerView.Adapter
的onBindViewHolder(@NonNull RecyclerViewHolder holder, int position, @NonNull List<Object> payloads)
方法 @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局部增量刷新 中的代码。
DiffUtil
、SortedList
进行局部增量刷新,提高刷新效率。和上面讲的传入payload
原理一样,这两个是Android默认提供给我们使用的两个封装类。这里我以DiffUtil
举例说明该如何使用。DiffUtil.Callback
的5个抽象方法,具体可参考DiffUtilCallback.javaDiffUtil.calculateDiff
方法返回比较的结果DiffUtil.DiffResult
。DiffUtil.DiffResult
的dispatchUpdatesTo
方法,传入RecyclerView.Adapter进行数据刷新。详细使用方法可参考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中,这样当数据源相似时,就可以提高缓存的复用率。
1.在onBindViewHolder方法中,去除冗余的setOnItemClick等事件。因为直接在onBindViewHolder方法中创建匿名内部类的方式来实现setOnItemClick,会导致在RecyclerView快速滑动时创建很多对象。应当把事件的绑定在ViewHolder创建的时候和对应的rootView进行绑定。
2.数据处理与视图绑定分离,去除onBindViewHolder方法里面的耗时操作,只做纯粹的数据绑定操作。当程序走到onBindViewHolder方法时,数据应当是准备完备的,禁止在onBindViewHolder方法里面进行数据获取的操作。
3.有大量图片时,滚动时停止加载图片,停止后再去加载图片。
4.对于固定尺寸的item,可以使用setHasFixedSize
避免requestLayout
。
1.降低item的布局层级,可以减少界面创建的渲染时间。
2.Prefetch预取。如果你使用的是嵌套的RecyclerView,或者你自己写LayoutManager,则需要自己实现Prefetch,重写collectAdjacentPrefetchPositions
方法。
以上都是针对RecyclerView的缓存机制展开的优化方案,其实还有几种方案可供参考。
1.取消不需要的item动画。具体的做法是:
((SimpleItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
2.使用getExtraLayoutSpace
为LayoutManager设置更多的预留空间。当RecyclerView的元素比较高,一屏只能显示一个元素的时候,第一次滑动到第二个元素会卡顿,这个时候就需要预留的额外空间,让RecyclerView预加载可重用的缓存。
以上就是RecyclerView性能优化的全部内容,俗话说:百闻不如一见,百见不如一干,大家还是赶紧动手尝试着开始进行优化吧!
6月5日,一张券商降薪截图在社交媒体疯传。截图提到,当日上午,某中字头头部券商召开大会,除了MD外全员降薪,且降薪不只是降奖金,而是直接降底薪。按照职级不同,SA1降6K,SA3降8K,VP降8K—10K。据了解,降薪大概率整体属实,但具体幅度有所差异,且不同区域、不同业务条线目前掌握的降薪情况也不尽相同。
今日,蔚来 CEO 李斌在 2023 高通汽车技术与合作峰会上爆料,蔚来第二代技术平台的全系车型已标配第三代骁龙座舱平台。
Meta公司周一(5月22日)推出了一个开源AI语言模型——大规模多语言语音(Massively Multilingual Speech, MMS)模型,可以识别和产生1000多种语言的语音——比目前可用的模型增加了10倍。研究人员表示,他们的模型可以转换1000多种语言,但能识别4000多种语言。
歌手孙燕姿在更新动态中回应了近日引发争议的“顶流AI歌手孙燕姿”,笑称粉丝已经接受她是“冷门”歌手,而AI成为了目前的顶流。
5月31日晚,荣耀方面对澎湃新闻记者表示,上海荣耀智能科技开发有限公司是荣耀位于上海的研究所,是荣耀在中国的5个研究中心之一,重点方向在终端侧核心软件、图形算法、通信、拍照等方面研究开发工作。荣耀强调,坚持以用户为中心,开放创新,与全球合作伙伴一起为用户提供最佳产品解决方案。
据北京市市场监督管理局公示信息,5月24日,苹果电子产品商贸(北京)有限公司因发布虚假广告被北京市东城区市场监督管理局处以20万元的行政处罚。
据外媒5月24日消息,全球最大的个人电脑制造商联想表示,在2023年1-3月期间,该公司裁员了约5%,这是由于PC市场不景气导致的。
日前,有网络博主号称拍摄到了小米首款汽车MS11的高清视频。从视频中可以看出,新车依旧包裹大面积的伪装,据该博主称,他之所以确定这是小米汽车,是因为靠近观察之后,发现它的三角形大灯轮廓和其最初手绘的小米汽车假想图几乎一模一样。
超过 350 名从事人工智能工作的高管、研究人员和工程师签署了这份由非盈利组织人工智能安全中心发布的公开信,认为人工智能具备可能导致人类灭绝的风险,应当将其视为与流行病和核战争同等的社会风险。
日前,以押注“颠覆性创新”著称的ARK Invest创始人Cathie Wood在接受媒体采访时表示,软件提供商将是人工智能狂潮的下一个受益板块。英伟达每卖出1美元的硬件,软件供应商SaaS供应商就会产生8美元的收入。
据报道,阿里巴巴研究员吴翰清已于近期离职,钉钉显示其离职时间是5月19日。在阿里内部,研究员的职级为P10。据消息人士透露,吴翰清离职后,选择AI短视频赛道创业,已经close一轮融资。对于上述消息,截至发稿,阿里尚未回应。
阿里巴巴集团官微宣布,2023年六大业务集团总计需新招15000人,其中校招超过3000人。同时表示,“近日,关于淘宝天猫、阿里云、菜鸟、本地生活各个业务裁员谣言传得很厉害,但谣言就是谣言。我们的招聘正在紧锣密鼓的进行。”
“现今每一个存在的应用都将被AI 2.0重构,我觉得整个AI大模型带来的机遇和技术浪潮,会比过去Windows和安卓大10倍。”李开复表示。
苹果发布Vision Pro头显,正式宣布开启空间计算时代;苹果还发布新款MacBook Air,新款Mac Studio,并展示了iOS17、iPadOS 17、macOS Sonoma和watchOS10等新系统;Vision Pro头显售价3499美元,将于2024年初正式在美国市场发售;华尔街并不看好Vision Pro,苹果股价周一创历史新高后由涨转跌。
5月25日,长城汽车就比亚迪秦PLUS DM-i、宋PLUS DM-i采用常压油箱,涉嫌整车蒸发污染物排放不达标的问题进行举报。
近日,一个名为“贾跃亭”的抖音账号悄然出现,带有“FF创始人、合伙人、首席产品及用户生态官, LeEco 乐视创始人”等标签,IP 地址显示为美国。
近日,苹果位于天猫的Apple Store官方旗舰店挂出直播预告,表示将在5月31日晚19时开启官方直播,这也是苹果官方在电商平台的全球首次直播。
5月29日消息,继上周远超预期的财报业绩预测引得股价和市值史诗级暴涨后,今日,英伟达(NVIDIA)创始人兼CEO黄仁勋穿着标志性的皮衣,意气风发地出现在台北电脑展COMPUTEX 2023上,在主题演讲期间先是现场给自家显卡带货,然后一连公布涉及加速计算和人工智能(AI)的多项进展。
前京东集团副总裁、京东探索研究院副院长梅涛自今年初离职后,确认在 AI 领域创业,成立生成式 AI 公司 HiDream.ai。