- 在使用RecyclerView或者阅读其源码前最好明确一些术语代表的概念,脱离具体实现细节,在抽象设计层思考RecyclerView 背后的模型。
- 先以RecyclerView的一个表现形式,一个可以上下滑动的列表作为切入点: 我们为什么偏向使用ListView/RecyclerView而非ScrollView+LinearLayout作为列表的实现方案? 因为列表的长度可能是很长的。从理想的使用角度看,一个LinearLayout当然可以容纳下数量庞大的ChildView来模拟一个长列表,不过现实中设备的内存是有限的,不可能为View无限分配空间。这样ListView出现了,它取巧的一点在于: 从感知上看,用户能看到的只是长列表的一部分(当然了,如果世界上存在屏幕非常非常长(100米长,哈?)的手机,ListView也没辙),列表自身只是一段数据, View是列表项展示的载体而非概念上的列表项,一个属于数据层,一个属于展示层。我们只需根据列表的内容将用户当前可以观察到的部分用View展现出来就能在感知上模拟出一个长列表 即使列表再长,受限于实际的展示区域,View的数量不会随着列表长度增加而增加。进一步为了优化性能,空间换时间,又引入了View回收复用机制。
- 上述ListView的解决方案规避了无限View问题。不过同时,一个分裂也被制造出来了:
- LinearLayout中的ChildView和整体列表项是一一对应的
- ListView在稳定状态下,可以做到ChildView对应一部分列表项, 但是一旦有数据改变(不稳定状态),在数据改变到ListView根据新数据刷新界面完毕的这个时间段内, ChildView的数据映射关系和新的数据是不一致的
- RecyclerView的一些概念:
- 稳定态: 数据和展示一致。
- 不稳定态: 数据变化,展示还没有刷新完,数据和展示不一致的阶段。
- Item: 列表项,属于一个列表,一个抽象层概念,View只是Item的展示载体, Item既有对应数据, 又可以有对应的View。 在RecyclerView中,ViewHolder就是Item的落地实现,RecyclerView在大多数概念级操作中,只关注ViewHolder,不关注ViewHolder对应的View,因为概念层的操作不应该涉及到展现层
- Position: Item在列表(算是数据层吧)中的位置.
- Index: View层概念,ChildView在ViewGroup中的索引。
- AdapterPosition: 同Position,RecyclerView这样称呼是因为Adapter算是Data在RecyclerView的代言人。
- LayoutPosition: 一个Item在上一次布局结束时在Data中的位置。
- LayoutPosition和AdapterPosition是矛盾的一体,大多时候(稳定态)item的这两个属性是相同的,但在不稳定状态下, 因为数据层发生了变化,视图还没有来得及刷新,导致Item在数据层的位置(AdapterPosition)已经被更新(因为数据确实已经改变了)了,但是LayoutPosition这个代表着最近一次布局结束后Item的Position需要等待刷新完毕才能更新,两者在这个时间段,是不一致的。 在视图根据新的数据刷新后,两者恢复一致,进入稳定态。这两个Position,在一次刷新过程中,都是需要的,
- 对Adapter来说(Data角度),AdapterPosition代表现在,LayoutPosition代表过去。
- 对RecyclerView来说(可以理解为View角度),LayoutPosition代表现在,AdapterPosition代表将来。