RecyclerView机制分析: Recycler

本文深入剖析了RecyclerView的Recycler组件,它不仅是View的回收站,更是View的提供者和管理者,负责生成、复用、回收和绑定View。文章介绍了detach与remove的区别,以及Scrap View和Recycled View的概念,详细阐述了Recycler的一级、二级和三级缓存机制,包括mAttachedScrap、mChangedScrap、mCachedViews和RecycledViewPool的工作原理。通过对ViewHolder的管理和复用,Recycler优化了列表性能,提高了用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. Recycler虽然命名上看,像是只承担了View回收的职责,其真正的定位是RecyclerView的View提供者(甚至是管理者), 包括生成新View, 复用旧View,回收View,重新绑定View等逻辑都被封装在Recycler中。外部调用者只需要调用Recycler的接口获取合适的View即可,不需要关心View获取和配置等具体细节,Recycler对外提供了View的回收和获取服务
  2. 先列一些概念:
    1. View的detach和remove:
      1. detach: 在ViewGroup中的实现很简单,只是将ChildView**从ParentView的ChildView数组中移除,ChildView的mParent设置为null, 可以理解为轻量级的临时remove, 因为View此时和View树还是藕断丝连, 这个函数被经常用来改变ChildView在ChildView数组中的次序。**View被detach一般是临时的,在后面会被重新attach
      2. remove: 真正的移除,不光被从ChildView数组中除名,其他和View树各项联系也会被彻底斩断(不考虑Animation/LayoutTransition这种特殊情况), 比如焦点被清除,从TouchTarget中被移除等
    2. RecyclerView的Scrap View:
      1. Scrap View指的是在RecyclerView中,处于根据数据刷新界面等行为, ChildView被detach(注意这个detach指的是1中介绍的detach行为,而不是RecyclerView一部分注释中的”detach”,RecyclerView一部分注释中的”detach”其实指得是上面的remove),并且被存储到了Recycler中,这部分ChildView就是Scrap View。
    3. ViewHolder有一个Flag: FLAG_TMP_DETACHED代表的就是1中介绍的detach, 这也印证了2的推测,RecyclerView将remove视为”detach”, detach视为”tmp_detach”
  3. Recycler**一般不会直接作用于View,其操作的对象一般是ViewHolder**。Recycler**分几个地方(代表不同层级)存放可复用的ViewHolder**:
    1. [一级缓存]:
Android E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.mysmartcity, PID: 29976 java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 7(offset:7).state:10 androidx.recyclerview.widget.RecyclerView{a237af0 VFED..... ........ 0,0-1080,2021 #7f090131 app:id/list}, adapter:com.example.mysmartcity.adapter.PayNews2Adapter@630a869, layout:androidx.recyclerview.widget.LinearLayoutManager@3de2ee, context:com.example.mysmartcity.ui.pay.PayNewsListActivity@f6877d0 at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6183) at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118) at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114) at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303) at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627) at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587) at androidx.recyclerview.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1391) at androidx.recyclerview.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1128) at androidx.recyclerview.widget.RecyclerView.scrollStep(RecyclerView.java:1841) at androidx.recyclerview.widget.RecyclerView.scrollByInternal(RecyclerView.java:1940) at androidx.recyclerview.widget.RecyclerView.onTouchEvent(RecyclerView.java:3391) at android.view.View.dispatchTouchEvent(View.java:14668) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3216) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2853) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222) at android.view.ViewGroup.dispatchTouchEvent(ViewGro
03-14
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值