RecyclerView 源码分析-开编

看了又看,任然对其一知半解。用了又用,发现其真的太美。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的区别:
  1. detach: 在ViewGroup中的实现很简单,只是将ChildView从ParentView的ChildView数组中移除,ChildView的mParent设置为null, 可以理解为轻量级的临时remove, 因为View此时和View树还是藕断丝连, 这个函数被经常用来改变ChildView在ChildView数组中的次序。View被detach一般是临时的,在后面会被重新attach。
  2. 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的描述

  1. RecycledViewPool作为第三级ViewHolder缓存,立足于RecyclerView之间的ViewHolder共享。
    RecycledViewPool是有容量限制的。

这里所的三级缓存还未理解到完整的结构。等到后面来完整的梳理。
以ViewType作为key来分类存放ViewHolder,每类ViewType都有单独容量限制,可以通过setMaxRecycledViews来为每种ViewType指定不同的容量限制。

  1. 被加入到RecycledViewPool的ViewHolder会被reset,只保留itemView使得View可以被复用, 基本是一个半裸的ViewHolder。

ps:这里也是之前没理解的每一个viewholder加入时,会被执行 resetInternal方法。

  1. RecycledViewPool在没有被显式指定的情况下,如果被调用,RecyclerView会自动创建一个。
  2. RecycledViewPool还有一套attach/detach机制来在Adapter 变化时选择性的释放旧缓存。

ViewCacheExtension

既然有了viewholder缓存的pool类,为什么又有一个viewCacheExtension类呢?它是做什么的呢?

  • 文档中所说是提供了一种额外缓存层级的来帮助开发者管理视图的类。
    调用java getViewForPosition时。如果没有合适的view Recycler会提供缓存的view来作为第一级的缓存。如果找不到合适的veiw,它会滴啊用 getViewForPositionAndType 在检查RecycledViewPool之前。

也就是说。ViewCacheExtension 是介于一级缓存和RecyclerViewPool的缓存之间。
其只提供了一个方法。getViewForPosition来提供缓存的类。

这样的三级缓存就呼之欲出。但是三级缓存有什么好处呢?通常不是一级缓存就能解决问题了吗?

暂时到这里吧。明天继续分析recycler中的代码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容