深入 RecyclerView 源码探究一:宏观设计

文章目录
  1. 1. 设计目的
  2. 2. 宏观设计
    1. 2.1. 关于数据展示
    2. 2.2. 关于 Flexible
    3. 2.3. 关于视图复用
  3. 3. 参考文献

生活好像没有我们想得那么简单,但也没有我们想得那样复杂,只不过,想吃芒果和樱桃,就得为了吃得起而努力。

时间如白驹过隙,大半年前,曾写过一篇从 ListView 到 RecyclerView 的用法浅析,当时,只是简单地谈了谈 ListView 与 RecyclerView 的对比与使用。而今,公司项目完全切到 RecyclerView,外界中,RecyclerView 的使用也愈发频繁。因此,在会用的前提下,结合源码深入探究 RecyclerView 便很有必要,打算分几篇来探讨下,这期且谈一谈其宏观设计。

设计目的

A flexible view for providing a limited window into a large data set.

以上简短的一句话来自官网。一言以蔽之,即一个给大型数据集提供有限窗口的弹性视图。

总结两点:

  • limited window, large data set.
  • flexible view.

下面看看其精美的宏观设计。

宏观设计

关于数据展示

RecyclerView 的目的之一就是在有限的窗口能够展示大量数据,和 ListView 一样,运用了设计模式中的适配器模式。结构图如下所示:

RecyclerView 继承自 ViewGroup,是装载子 View 的容器之一,其通过 Adapter,整合要展示数据的内容和类型,生成相应的 ViewHolder,再设置相应的 itemView,从而展示出来。其中,通过实现 Adapter 中的 onCreateViewHolder() 创建 ViewHolder,onBindViewHolder() 绑定数据,Data 才能转化生成用于展示 View 的 ViewHolder。

关于 Flexible

RecyclerView 高度解耦,异常灵活,从其布局、装饰和动画上能体现其极好的弹性。

I. 布局

通过布局管理器 LayoutManager 可以控制其显示方式。结构图如下所示:

RecyclerView 的布局全权由 LayoutManager 负责,其获取 ViewHolder 中的 itemView,根据定义好的布局模式(包括线性布局、网格布局和瀑布流布局),对 itemView 进行布局,最后添加到 RecyclerView 中显示出来。此外,开发者可以根据自己的需求,重写相关的方法,进行自定义布局。

II. 装饰

通过 ItemDecoration 可以控制 Item 间的间隔(可绘制)。

装饰需要实现 ItemDecoration 类中的抽象函数。RecyclerView 内部调用 onDraw() 方法时执行 ItemDecoraton 的 onDraw() 方法,源码如下:

1
2
3
4
5
6
7
8
9
@Override
public void onDraw(Canvas c) {
super.onDraw(c);

final int count = mItemDecorations.size();
for (int i = 0; i < count; i++) {
mItemDecorations.get(i).onDraw(c, this, mState);
}
}

而后,在 draw 的时候执行 ItemDecoration 的 onDrawOver() 方法。源码如下:

1
2
3
4
5
6
7
8
9
10
@Override
public void draw(Canvas c) {
super.draw(c);

final int count = mItemDecorations.size();
for (int i = 0; i < count; i++) {
mItemDecorations.get(i).onDrawOver(c, this, mState);
}
// ...
}

最后,在计算 itemView 的 padding 时,将 getItemOffsets 得到的 Rect 加入其中,这样空出装饰内容的区域。开发者可以自定义 ItemDecoration,以实现各种各样的装饰。

III. 动画

通过 ItemAnimator 可以控制 Item 增删的动画。

当添加、删除甚至更改 Item 时,可以通过动画来体现这种变化,RecyclerView 提供了一种非常灵活的动画机制。结构图如下:

数据改变触发动画,通常调用 Adapter 中的 notify 系列方法。notify 系列的方法可以看作是发出一个事件,这里,Adapter 和 RecyclerView 的工作机制是一个典型的观察者模式

RecyclerView 是观察者,Adapter 是可观察的,设置 Adapter 时,RecyclerView 订阅观察事件,Adapter 中的数据发生改变时,会通知 RecyclerView,其获取通知后,调用一系列方法,触发重新布局。接着,布局过程中,再调用一系列方法,将动画信息存储到 ViewInfoStore 中。最后,布局结束时,ViewInfoStore 统一处理,通过 Callback 中的方法调用 ItemAnimator 中的方法,再执行动画。

ItemAnimator 铸就了 RecyclerView 动画的灵活性,开发者通过继承 ItemAnimator,实现或重写其方法,来生成各种各样的效果。

关于视图复用

有限的窗口展现大量数据的视图,并且有着很好的性能,视图复用机制在这里起着举足轻重的作用。结构图如下:

橙色列表是一个 Recycler,底部还有个 RecycledViewPool。

Recycler

A Recycler is responsible for managing scrapped or detached item views for reuse.

大意即 Recycler 负责管理成为碎片的视图或者 detached 视图的复用。

RecycledViewPool

RecycledViewPool lets you share Views between multiple RecyclerViews.

大意即 RecycledViewPool 能让你在多个 RecyclerView 之间分享视图。

实际上,ViewHolder 的创建和绑定都由 Recycler 执行。此外,LayoutManager 获得 ViewHolder 的 itemView,也由 Recycler 提供。Recycler 里有几个 ViewHolder 的容器,用来存储不同状态的 ViewHolder,以便复用。其中,通过 ViewCacheExtension 类,开发者可以自定义复用机制。而 RecycledViewPool,可以从外部对多个 RecyclerView 设置同一个 RecycledViewPool,以实现多个 RecyclerView 中 ViewHolder 的复用。

至此,关于 RecyclerView 的宏观设计探究完毕,后续将分几篇从主要流程和机制方面展开探究。

本人才疏学浅,如有疏漏错误之处,望读者中有识之士不吝赐教,谢谢。

1
Email: [email protected] / WeChat: Wolverine623

您也可以关注我个人的微信公众号码农六哥第一时间获得博客的更新通知,或后台留言与我交流

参考文献

1.http://www.jianshu.com/p/9ddfdffee5d3