日志.png 红框1是 RecyclerView 向下滑动操作的日志,第三行5个卡位的显示都是重新创建的 ViewHolder ;红框2是再次向上滑动时的日志,第一行5个卡位的重新显示用的 ViewHolder...,后面2个卡位的 ViewHolder 则是重新创建的,而且5个卡位都调用了 onBindViewHolder() 重新绑定数据; 那么, Q3:接下去不管是向上滑动还是向下滑动,滑动几次,都不会再有...onCreateViewHolder() 的日志了,也就是说 RecyclerView 总共创建了17个 ViewHolder,但有时一行的5个卡位只有3个卡位需要重新绑定数据,有时却又5个卡位都需要重新绑定数据...5个卡位都是用的复用的,而从 ViewPool 里拿的复用需要重新绑定数据,才会这样只有三个卡位需要重新绑定数据。...而至于为什么会创建了17个 ViewHolder,那是因为再第四行的卡位要显示出来时,ViewPool 里只有3个缓存,而第四行的卡位又用不了 mCachedViews 里的2个缓存,因为这两个缓存的是
这里的ViewHolder是已经被抹除数据的,没有任何绑定的痕迹,需要重新绑定数据。...如果还没有,则最终去mRecyclerPool找,如果itemType类型匹配对应的ViewHolder,那么返回实例,让它重新绑定数据。...如果mRecyclerPool也没有返回ViewHolder才会调用createViewHolder()重新去创建一个。...性能优化方案 根据上面我们对缓存机制的了解,我们可以简单得到以下几个大方向: 1.提高ViewHolder的复用,减少ViewHolder的创建和数据绑定工作。...应当把事件的绑定在ViewHolder创建的时候和对应的rootView进行绑定。 2.数据处理与视图绑定分离,去除onBindViewHolder方法里面的耗时操作,只做纯粹的数据绑定操作。
参考简答: RecyclerView通过一系列精细的缓存机制优化性能,包括: AttachedScrap 作用:存储暂时从RecyclerView中分离,但很快会重新绑定和重新使用的ViewHolders...特点:它们主要用于动画处理,如移动动画或者删除动画,因为RecyclerView可以直接访问这些ViewHolders,而无需通过Adapter重新创建。...ViewHolder:代表列表中的每个项的视图容器。通过ViewHolder,RecyclerView可以有效地重用视图,减少视图创建的开销。 ItemAnimator:负责处理项变更时的动画。...如果可以,RecyclerView会重新绑定新数据到这个ViewHolder上,而不是创建新的ViewHolder。...清理和完成:最后,RecyclerView完成更新流程,清理所有临时标记和缓存。 实战使用 问题: 在RecyclerView中,如何只刷新列表项中的某个控件而不是整个item?
ViewHolder 的实践:一般情况下我们是在 onBindViewHolder 方法中绑定数据,但是如果是多个条目,那么这种写法就会非常臃肿,这种情况下就可以吧绑定数据的代码写在 ViewHolder...ViewHolder和 item 实际上是绑定的,所以缓存了 ViewHolder 也就相当于缓存了 item。...从Cache 中拿到的缓存可直接进行使用,无需重新创建可绑定数据。...如果在上面的 4 级缓存中都没有,则会重新创建 ViewHolder。最终调用的是 onCreateViewHolder,由用户自行创建。...每看到一次,这个方法就会执行一次 7,你可能不知道的 RecyclerView 性能优化策略 不要在 onBindViewHolder 方法中创建点击事件 在创建 ViewHolder 的时候创建
ViewHolder 的实践:一般情况下我们是在 onBindViewHolder 方法中绑定数据,但是如果是多个条目,那么这种写法就会非常臃肿,这种情况下就可以吧绑定数据的代码写在 ViewHolder...ViewHolder和 item 实际上是绑定的,所以缓存了 ViewHolder 也就相当于缓存了 item。...从Cache 中拿到的缓存可直接进行使用,无需重新创建可绑定数据。...如果在上面的 4 级缓存中都没有,则会重新创建 ViewHolder。最终调用的是 onCreateViewHolder,由用户自行创建。...多个 RecyclerView 共用 RecycledViewPoll 注意这个 RecycledViewPool 不是 四级缓存中的 RecyclerViewPool RecyclerView 会默认给自己创建一个
当调用notifyDataSetChanged()方法时,ViewHolder会进入上面的一级缓存mAttachedScrap中,而不是进入缓存池pool中,这样的好处:1)不会存在缓存池pool满的问题...view,而不是新建view)。...RecyclerView开发工程师将创建和绑定移到前一帧,使UI线程与渲染线程同时工作,在一个条目即将进入视野时预取数据。...在 25.1 版本中,预取操作被分为单独的创建/绑定操作,比对整组条目操作更容易被纳入 UI 线程的空隙中。...ViewHolder不会重新创建,也不会重新bindView,这样某些ItemView的图片是View属性动画变换后的图片,导致不是自己想要的结果。
Adapter: 连接数据和UI,负责创建ViewHolder、绑定数据以及处理数据集合变化。在实际应用中,适配器的设计影响着整个列表的性能和扩展性。...ViewHolder创建和绑定: RecyclerView会调用Adapter的onCreateViewHolder方法创建ViewHolder,并通过onBindViewHolder将数据绑定到ViewHolder...当Item被滑出屏幕时,ViewHolder会被复用,而不是重新创建。 优势包括: 减少内存消耗: 通过复用ViewHolder,减少了View的创建和销毁,降低了内存开销。...当ItemView滑出屏幕时,对应的ViewHolder会被缓存,而不是立即销毁。当需要新的ItemView时,可以从缓存中获取ViewHolder,避免频繁的View创建和销毁。...复用机制: 当新的数据需要显示时,RecyclerView会调用Adapter的onBindViewHolder方法,将新的数据绑定到已存在的ViewHolder上,而不是创建新的View。
了,所以重新绑定数据,发生了闪烁 我们验证下上面的猜想 class TabMainCategoryItemHolder(val binding: ItemTabMainCategoryItemBinding...) : RecyclerView.ViewHolder(binding.root) { //缓存上次的itemID...holder,都需要重新设置图片跟文案,所以产生了闪烁 这里,问题来了,每次刷新,后面五个holder的初始ID都是0,说明每次刷新,都新建了五个viewHolder,viewHolder不是复用的?...5个,在绑定新的数据,复用holder,还需要重新创建5个新的holder 分析到此,其实解决方案已经非常清楚了 解决方案1:把RecyclerViewPool的最大的缓存数量设置为10 rvItemCategory.recycledViewPool.setMaxRecycledViews...(0, 10) 可以看下效果 除了上面的方案,其实还有另外一个修复方案,继续看下RecyclerView内部的源码 if (viewHolder.isInvalid() && !
RecyclerView可以看作是ListView的进化版本,当然RecyclerView并不是继承ListView的,RecyclerView直接继承于ViewGroup父类。...在使用RecyclerView之前,需要自定义一个继承自RecyclerView.Adapter的适配器,将数据与每一个item的界面进行绑定。...需要注意的是编写Adapter面向的是ViewHolder而不在是View了,复用的逻辑被封装了起来,实现更加简单。...onBindViewHolder:主要用来把数据绑定到视图上。 除了上面两个主要元素,通常还会使用到如下三个类: ViewHolder:维持了所有被数据填充的实体的视图的引用。...vewHolder = new ViewHolder(view); return vewHolder; } // 将数据与界面进行绑定的操作 @Override
得益于RecyclerView设计时的解耦,ItemView的创建、绑定和复用对LayoutManager来说都是不可见的,LayoutManager只需要关心如何布局ItemView即可。...会被重置,因此从mRecyclerPool查找缓存时只需要viewType相等即可,最终会调用Adapter的onBindViewHolder()重新绑定数据。...holder.isBound() || holder.needsUpdate() || holder.isInvalid()) { // 如果ViewHolder需要重新绑定,则调用...时,主要的判断条件都是holder.getLayoutPosition() == position,得到的ViewHolder不用重新绑定。...后再调用holder.resetInternal()重置,tryGetViewHolderForPositionByDeadline(…)方法最后会对未绑定的ViewHolder重新绑定数据。
,表示ViewHolder是存放在Scrap缓存中 1.2 flag FLAG_BOUND:ViewHolder对应的View已经绑定好了数据,无需重新绑定 FLAG_UPDATE:数据发生了变化,View...需要重新绑定 FLAG_INVALID:数据失效了,View需要重新绑定 FLAG_REMOVED:数据从数据源中删除,View在消失动画中仍然有用 FLAG_NOT_RECYCLABLE:ViewHolder...如果使用GridLayoutManager建议设置为列的个数 该缓存中的ViewHolder无需重新绑定,只要ViewHolder的position和数据源中的position和itemType对应上了...>,每个itemType对应的ScrapData的缓存大小默认值是5,可以修改缓存大小 该缓存中的ViewHolder需要重新绑定数据 可以提供给多个RecyclerView共享 3....需要重新绑定 ?
Scrap Cache 的大小不是由 LayoutManager 来控制的,而是由 RecyclerView 自己维护的。...如果 Scrap Cache 中也没有可重用的 View,RecyclerView 会调用 LayoutManager 的 createViewHolder() 方法创建一个新的 ViewHolder,...这就意味着,如果你的 ViewHolder 需要重新绑定数据,就必须在 RecyclerView 中手动调用 onBindViewHolder 方法。...如何优化 RecyclerView 的缓存机制 为了优化 RecyclerView 的缓存机制,我们可以采取以下措施: 减少 ViewHolder 的创建次数和内存占用 可以使用 DataBinding...ViewHolder 类重新加载导致的额外性能损耗。
拿到 ViewHolder 实例后,就得判断是否需要为它绑定数据: public class RecyclerView { public final class Recycler {...需要更新或者无效了, 则重新为其绑定数据 else if (!...holder.isBound() || holder.needsUpdate() || holder.isInvalid()这个条件,从缓存池命中的 ViewHolder 就得重新绑定数据。...RecyclerView 重新布局表项是这样进行的:先回收现存表项到缓存池,再重新填充它们。...因为这些表项的 ViewHolder 实例在重绘之前都被“无效化”了,所以即使数据没变也逃不掉重新执行绑定数据的操作。 可见notifyDataSetChanged()有多昂贵!
mRecyclerPool(缓存池),当cacheView满了后或者adapter被更换,将cacheView中移出的ViewHolder放到Pool中,放之前会把ViewHolder数据清除掉,所以复用时需要重新...匹配holder——>获取失败,从CacheView中获取,也是通过pos获取holder缓存 ——>获取失败,从自定义缓存中获取缓存——>获取失败,从mRecyclerPool中获取 ——>获取失败,重新创建...而新出现的position=9数据由于在mRecyclerPool中还是找不到相应type的ViewHolder,所以还是会走onCreateViewHolder和onBindViewHolder方法。...所以就直接复用了,并调用onBindViewHolder方法绑定数据。...缓存的其实就是缓存item的view,在Recyclerview中就是viewholder。 cachedView就是mCacheViews缓存区中的view,是不需要重新绑定数据的。
可以在不完全脱离父 RecyclerView 的情况下重用 Scrap 视图,如果不需要重新绑定则不修改,或者如果视图被认为是脏的则由适配器修改。...Dirty (view): 脏view,dirtyView显示在界面上上必须重新绑定。...mCachedViews 一级缓存:ViewHolder数据还在,只有原来的position可用,不需要重新绑定数据mCachedViews 默认大小为 2RecycledViewPool 二级缓存:ViewHolder...数据重置,需要重新绑定数据detach操作,是一种轻量级的分离,只会把这个View在ViewGroup的children数组中的引用设为null,并设置他的parent为null。...viewHolder, int direction) { //滑动处理 } }; //创建helper对象 ItemTouchHelper itemTouchHelper
ViewHolder holder = null; // 第一步 从 mChangedScrap 中获取 // PreLayout从名字可以看出,它不是真实的布局,不过我不是特别清楚...// 如果缓存中都没有,就需要重新创建 holder = mAdapter.createViewHolder(RecyclerView.this, type...holder.isBound() || holder.needsUpdate() || holder.isInvalid()) { // ... // 没有绑定就重新绑定...RecyuclerPool 的方式获取,如果连缓存池中都没有,那么 Recycler 只好调用 Adapter#createViewHolder 重新创建,这个名称是我们的老朋友了,而且还是在 Adapter...灰色的是小 T 同学的手机屏幕,查看聊天记录的时候,RecyclerView 不会每次都创建新的 ViewHolder,也不会一次性将所有的 ViewHolder 都建好,减少了内存和时间的损耗,所以,
position, null) ; * * 这是一个结构性的变化事件 ; * 表示在数据集中的其它元素仍然被认为是最新的数据 , 这些数据不会被重新绑定...被修改的元素在原数据集中首个元素的位置索引 ; int itemCount 参数 : 数据集中被修改元素个数 ; 注意 : 这是一个结构性的变化事件 ; 表示在数据集中的其它元素仍然被认为是最新的数据 , 这些数据不会被重新绑定...itemCount, null) ; * * 这是一个结构性的变化事件 ; * 表示在数据集中的其它元素仍然被认为是最新的数据 , 这些数据不会被重新绑定...extends RecyclerView.ViewHolder { TextView text; public ViewHolder(@NonNull...相关资料 ---- 官方文档 : 使用 RecyclerView 创建动态列表 : https://developer.android.google.cn/guide/topics/ui/layout
参数 : 元素移动前的位置 ; int toPosition 参数 : 元素移动后的新位置 ; 注意 : 这是一个结构性的变化事件 ; 表示在数据集中的其它元素仍然被认为是最新的数据 , 这些数据不会被重新绑定...toPosition 位置 ; * * 这是一个结构性的变化事件 ; * 表示在数据集中的其它元素仍然被认为是最新的数据 , 这些数据不会被重新绑定...; 注意 : 该方法不指定数据集发生了哪些变化 , 强制要求任何观察者对象去呈现所有存在的 item 条目和结构 , 这些数据可能已经失效 ; 布局管理器 LayoutManager 会强制所有数据重新绑定..., 但是单独的 item 元素组件需要重新被绑定 ; 代码示例 : 先移动数据 , 再删除三个数据 ; // 先移除第 0 个 names.remove...; * 这样有助于动画和可视化对象的持续 , 但是单独的 item 元素组件需要重新被绑定 ; * * 如果你正在写一个适配器 , 使用该方法
可以在不同的recyclerView中使用相同的pool。也可以让其自己创建。 ScrapData类。 这个类的英语注释没有看懂。当时其实应该是保存viewholder的缓存的地方。...无论是在构建还是在绑定数据时。而且还提供了平均绑定数据和创建viewholder的计时。后面一个功能没有看懂。...View被detach一般是临时的,在后面会被重新attach。...detach行为,而不是RecyclerView一部分注释中的”detach”,RecyclerView一部分注释中的”detach”其实指得是上面的remove),并且被存储到了Recycler中,这部分...RecycledViewPool在没有被显式指定的情况下,如果被调用,RecyclerView会自动创建一个。
也就是说,只能是RecyclerView的ViewHolder被滑出屏幕后,再滑回来显示的情景。 也不难看出,从mCachedViews中,我们取得的ViewHolder是不需要重新绑定数据的。...当我们在mAttachedScrap & mChangedScrap和mCachedViews中均未获得ViewHolder时,我们会尝试从mViewCacheExtension中获取View并创建ViewHolder...然后RecyclerView帮我们找到View对应的ViewHolder。这一层缓存的实现完全可以靠开发者的想象。 值得注意的是,这一层如果能成功获得ViewHolder,也是不会绑定数据的。...这样,当我们刷新数据时,RecyclerView就能确认是否数据没有变化,ViewHolder也直接复用,减少重新布局的烦恼。同时,由于ViewHolder没有变动,可以去掉动画。...然后那些优化方式,为什么要当作外部API来提供,而不是直接在内部帮我们优化,限制又是什么?只有这样,我们才能感受到RecyclerView的巧妙设计,也为我们后续自己工作中的设计提供思路。
领取专属 10元无门槛券
手把手带您无忧上云