2.getScrapOrHiddenOrCachedHolderForPosition – mAttachedScrap 、mCachedViews
3.getScrapOrCachedViewForId – mAttachedScrap 、mCachedViews (ViewType,itemid)
4.mViewCacheExtension.getViewForPositionAndType – 自定义缓存
5.getRecycledViewPool().getRecycledView – 从缓冲池里面获取
- getChangedScrapViewForPosition 获取ChangedScrapView通过Position
是从mChangeScrap的List里取的,一般与动画相关 — 一级缓存
通过position或者id取,都是for循环遍历List,然后出去holder,在if判断,如果符合条件就返回holder
- 如果没取到,if (holder == null),那就getScrapOrHiddenOrCachedHolderForPosition(获取Scrap/Hidden/Cached的Holder–For–Position)
**mAttachedScrap 、mCachedViews从这两列表里取,
mAttachedScrap=一级缓存,mCachedViews=二级缓存**
- 如果还是没取到,getScrapOrCachedViewForId,跟第二步一样,只不过第二步用的Position取,这个用的id取
**mAttachedScrap 、mCachedViews (ViewType,itemid)
mAttachedScrap=一级缓存,mCachedViews=二级缓存**
- 还没取到
mViewCacheExtension.getViewForPositionAndType
在自定义缓存里取,一般用不到
mViewCacheExtension三级缓存
- 还没取到去RecycledViewPool里取
RecycledViewPool是第四级缓存,他的构造上面说了
- 四级缓存都没取到,mAdapter.createViewHolder,那就调用mAdapter的createViewHolder去创建
- 创建了ViewHolder以后就得去绑定,tryBindViewHolderByDeadline
最后会调到自己写的Adapter中的onBindViewHolder
多级缓存的目的:肯定是为了性能
回收
回收就是当ItemView划出屏幕的时候,将ViewHolder存到集合(List)里。
- LinearLayoutManager.onLayoutChildren --> detachAndScrapAttachedViews --> scrapOrRecycleView
- LinearLayoutManager.onLayoutChildren
onLayoutChildren这个方法其实跟onLayout差不多,但是onLayout需要处理很多代码,但是onLayoutChildren其实是简化了onLayout。
补充(onLayout会调到onLayoutChildren,如果自定义LayoutManager,那重写onLayoutChildren就省去很多onLayout的代码):
RecyclerView.onLayoutChildren里备注了,如果要自定义LayoutManager那就一定要实现这个方法,但是有点坑,谷歌应该定义成抽象的,缺没有
onLayoutChildren这个方法的起点就是onLayout()
- RecyclerView.detachAndScrapAttachedViews
- scrapOrRecycleView(废弃 or 回收 View)
- itemView的回收的主流程就在scrapOrRecycleView
scrapOrRecycleView
具体选择哪个缓存,scrap还是RecycleView
if (viewHolder.isInvalid()) 如果viewHolder被移出屏幕那就走
->recycler.recycleViewHolderInternal(viewHolder); (Internal内部)
else -> recycler.scrapView(view);
具体流程:
–> ①.recycler.recycleViewHolderInternal(viewHolder); – 处理 CacheView 、RecyclerViewPool 的缓存
- –> 1.ViewHodler改变 不会进来 – 先判断mCachedViews的大小
–> mCachedViews.size 大于默认大小 — recycleCachedViewAt
– >addViewHolderToRecycledViewPool — 缓存池里面的数据都是从mCachedViews里面出来的
- –> 2.addViewHolderToRecycledViewPool --> getRecycledViewPool().putRecycledView(holder);
–> scrap.resetInternal(); ViewHolder 清空
–> ②.recycler.scrapView(view);
recycler.recycleViewHolderInternal(viewHolder) – 处理 CacheView 、RecyclerViewPool 的缓存(scrapOrRecycleView方法里的 if 分支)
- 先判断mCachedViews列表的大小是不是大于规定的最大值mViewCacheMax,大于的话就走recycleCachedViewAt()
- 不管mCachedViews大小有没有超最大值,都会将holder,add进mCachedViews列表
- 看如果超过最大mViewCacheMax的recycleCachedViewAt方法
注意入参是0
**1.先 ViewHolder viewHolder = mCachedViews.get(cachedViewIndex);
2.将取出的viewHolder,传入addViewHolderToRecycledViewPool(viewHolder, true);–顾名思义:添加ViewHolder到缓存池
3.将mCachedViews.remove(cachedViewIndex)**
总结:
- addViewHolderToRecycledViewPool
- putRecycledView
所以RecycledViewPool里面的ViewHolder是个空的,但是mCachedViews列表里的ViewHolder却是有数据的ViewHolder
recycler.scrapView(view) (scrapOrRecycleView方法里的 else 分支)
如果不是划出屏幕的缓存
其实就很简单了,直接往mAttachedScrap或者mChangedScrap列表里add(holder),第一级缓存
总结
效果:
实现自定义LayoutManager
先实现一个
这就没啥好说的。
重点在于自定义LayoutManager,之前使用的是系统的LinearLayoutManager
- 继承RecyclerView.LayoutManager
自定义LayoutManager,都是需要继承这个的
- 继承完以后发现有一个方法要实现
设置默认的LayoutParams
查看LinearLayoutManager是怎么做的
直接复制过来就行,自己的也这样实现
- onLayout必须实现,上面有说过,要自定义LayoutManager必须要实现onLayoutChildren,谷歌写的log里说的,但是他没给弄成抽象
- 在onLayoutChildren主要实现的就是布局onLayout,还有参考LinearLayoutManager他还实现了RecyclerView四级缓存的回收、复用都实现了。
回收:看上面源码分析的步骤,回收里调用的是detachAndScrapAttachedViews
查看LinearLayoutManager源码,复用其实也有调用到,fill()方法
fill一直往下点(看上面源码分析:)
–> fill --> layoutChunk --> layoutState.next --> addView(view);
layoutState.next。这个就是跳出LinearLayoutManager执行到RecyclerView的方法。
是一个while循环然后遍历,在.next取出各个View,通过
final View view = recycler.getViewForPosition(mCurrentPosition);
**所以我们自己写自定义LayoutManager的onLayoutChildren的时候,回收复用就仿照LinearLayoutManager来
回收=detachAndScrapAttachedViews
复用=for遍历然后通过position取出View,最后在addView,
View view = recycler.getViewForPosition(mCurrentPosition)这个
**
- 回收复用写完
算上被划走的那张卡片,其实只需要布局4张卡片
依次减小的三张+最后一张=最底下那张(也就是最下面其实是两张一样大小的)
先布局最底下的那张卡片,然后依次向上布局,对应list也就是布局0,1,2,3
- onlayout
- 现在布局完了就是item在屏幕中间叠在一起,需要有减小的效果,得把卡片向下平移再缩小一点
现在的效果就是一个静态的
自定义ItemTouchHelper
需要能上下左右滑动,需要自定义ItemTouchHelper
ItemTouchHelper一个是滑动,一个是拖拽。现在只需要滑动
- extends ItemTouchHelper.SimpleCallback
在拖拽方法啥也不动,滑动方法把划走的DataBean删了,然后在添加回来刷新列表(数据多可以不添回来,我这循环播放所以添回来)
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-IHezrTiR-1715843464749)]
[外链图片转存中…(img-dQFwPz8j-1715843464750)]
[外链图片转存中…(img-HOoJPaVJ-1715843464751)]
[外链图片转存中…(img-rjNUDloK-1715843464752)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!