看了又看,任然对其一知半解。用了又用,发现其真的太美。RecyclerView的设计和书写实在是太惊艳了,日常又使用的相当频繁。虽然之前就看过其他的源码分析,故打算花点时间来亲子动画,对其来个了解,希望能向好的框架学习,写出这样优秀的代码。
开始
既然是开始,当然是先从RecyclerView本身开始。
有趣的类:
AdapterDataObserver 和RecyclerViewDataOberver类
1.首先,AdapterDataObserver是一个抽象类。
- Observer base class for watching changes to an {@link Adapter}.
2.后者是前者的一个内部实现类
来看他的具体方法。
里面还有判断是不是每次都是增量式完成layout的。
ChildHelper类
- Helper class to manage children.
它是recyclerView的包装类。提供两套方法来通知子类。一种是忽略隐藏的view的。一种是不过滤的。
其中的bucket类在recycylerView中很常见,进行位运算的类?!
Bucket
其本身是一个链表的结构。
如果一个对象有大量的是与非的状态需要表示,通常我们会使用BitMask 技术来节省内存,在 >Java 中,一个 byte 类型,有 8 位(bit),可以表达 8 个不同的状态,而 int 类型,则有 32 >位,可以表达 32 种状态。再比如Long类型,有64位,则可以表达64中状态。一般情况下使用一个>Long已经足够我们使用了。但如果有不设上限的状态需要我们表示呢?在ChildHelper里有一个静>>态内部类Bucket
可以看到,Bucket是一个链表结构,当index大于64的时候,它便会去下一个Bucket去寻找,所以,Bucket可以不设上限的表示状态。
CallBack
内部类CallBack其实就是RecyclerView来实现其方法
Recycler类
也是一个内部类,是管理回收(scrapped)或者分离(detached)的内部管理类。
有layoutmanager来控制recycler中获得对应的view
scrapped view
dirty or clean
dirty view需要重绘,而clean view不需要重绘和布局,直接由layoutmanager而使用
其中保存这 attached viewholder 和 changed viewholder
mUnmodifiableAttachedScrap 发现有一个集合。是有attached viewholder复制而来的不可重绘的副本。(通过java Collections.unmodifiableList()
)
[参考链接-Collections方法说明][1]
阅读参考链接,得知,这是一种通用的重构中使用的手法。
在《重构——改善既有代码的设计》一书中,有一种重构手法叫Encapsulate Collection >,(封装集合)
使用这种方法重构的意义:就好比我们网上购物一样,你可以往购物车添加自己想买的东西,但是>商户不能在不通知顾客(我们)的情况下,就任意的添加商品,并修改商品的价格等,入口只能是>一个,也就是在顾客手中。比喻可能不是很恰当,反正意思大概就是这样。
这个方法还是挺有意思的。将自己所包含的集合封装起来提供给其他的使用者。避免使用的时候发生改变。
其中有一个RecyclerViewPool的内部类
RecycledViewPool lets you share Views between multiple RecyclerViews.
可以在不同的recyclerView中使用相同的pool。也可以让其自己创建。
ScrapData类。 这个类的英语注释没有看懂。当时其实应该是保存viewholder的缓存的地方。无论是在构建还是在绑定数据时。而且还提供了平均绑定数据和创建viewholder的计时。后面一个功能没有看懂。
根据viewType 来保存scrapData 再有srcapData来保存viewHolder.这里看到默认的堆大小为5,就是说相同种类的viewholder默认的保存数量是5个?
runningAverage方法? 来的时间的权重在3/4 新时间占1/4
factorIn...方法和 willxxxInTime方法提供的是一种时间的判断??
attachCount的计数
[对缓存机制的理解][2]
这里文章里面对缓存机制的描述相当的透彻。
- 首先是,View的detach和remove的区别:
- detach: 在ViewGroup中的实现很简单,只是将ChildView从ParentView的ChildView数组中移除,ChildView的mParent设置为null, 可以理解为轻量级的临时remove, 因为View此时和View树还是藕断丝连, 这个函数被经常用来改变ChildView在ChildView数组中的次序。View被detach一般是临时的,在后面会被重新attach。
- remove: 真正的移除,不光被从ChildView数组中除名,其他和View树各项联系也会被彻底斩断(不考虑Animation/LayoutTransition这种特殊情况), 比如焦点被清除,从TouchTarget中被移除等。
RecyclerView的Scrap View:
Scrap View指的是在RecyclerView中,处于根据数据刷新界面等行为, ChildView被detach(注意这个detach指的是1中介绍的detach行为,而不是RecyclerView一部分注释中的”detach”,RecyclerView一部分注释中的”detach”其实指得是上面的remove),并且被存储到了Recycler中,这部分ChildView就是Scrap View。
ViewHolder有一个Flag: FLAG_TMP_DETACHED代表的就是1中介绍的detach, 这也印证了2的推测,RecyclerView将remove视为”detach”, detach视为”tmp_detach”其中还有对于RecyclerViewPool的描述
- RecycledViewPool作为第三级ViewHolder缓存,立足于RecyclerView之间的ViewHolder共享。
RecycledViewPool是有容量限制的。
这里所的三级缓存还未理解到完整的结构。等到后面来完整的梳理。
以ViewType作为key来分类存放ViewHolder,每类ViewType都有单独容量限制,可以通过setMaxRecycledViews来为每种ViewType指定不同的容量限制。
- 被加入到RecycledViewPool的ViewHolder会被reset,只保留itemView使得View可以被复用, 基本是一个半裸的ViewHolder。
ps:这里也是之前没理解的每一个viewholder加入时,会被执行 resetInternal方法。
- RecycledViewPool在没有被显式指定的情况下,如果被调用,RecyclerView会自动创建一个。
- RecycledViewPool还有一套attach/detach机制来在Adapter 变化时选择性的释放旧缓存。
ViewCacheExtension
既然有了viewholder缓存的pool类,为什么又有一个viewCacheExtension类呢?它是做什么的呢?
- 文档中所说是提供了一种额外缓存层级的来帮助开发者管理视图的类。
调用java getViewForPosition
时。如果没有合适的view Recycler会提供缓存的view来作为第一级的缓存。如果找不到合适的veiw,它会滴啊用 getViewForPositionAndType 在检查RecycledViewPool之前。
也就是说。ViewCacheExtension 是介于一级缓存和RecyclerViewPool的缓存之间。
其只提供了一个方法。getViewForPosition来提供缓存的类。
这样的三级缓存就呼之欲出。但是三级缓存有什么好处呢?通常不是一级缓存就能解决问题了吗?