前言
前文已经在整体上对RecyclerView的实现作出了剖析,但是有些细节上,我并没有做太过深入的解释,“续一”将针对RecyclerView的动画作更深入剖析。同样,文中所示源码版本为23.2.0。本文欢迎转载,不需要注明出处。
pre&post layout
在RecyclerView中存在一个叫“预布局”的阶段,当然这个是我自己作的翻译,本来叫pre layout,与之对应的还有个叫post layout的阶段,它们分别发生在真正的子控件测量&布局的前后。其中pre layout阶段的作用是记录数据集改变前的子控件信息,post layout阶段的作用是记录数据集改变后的子控件信息及触发动画。
void dispatchLayout() {
...
if (mState.mLayoutStep == State.STEP_START) {
dispatchLayoutStep1();
...
dispatchLayoutStep2();
}
dispatchLayoutStep3();
...
}
方法dispatchLayout()会在RecyclerView.onLayout()中被调用,其中dispatchLayoutStep1就是pre layout,dispatchLayoutStep3就是post layout,而dispatchLayoutStep2自然就是处理真正测量&布局的了。
首先来看看pre layout时都记录了什么内容:
private void dispatchLayoutStep1() {
...
if (mState.mRunSimpleAnimations) {
// Step 0: Find out where all non-removed items are, pre-layout
int count = mChildHelper.getChildCount();
for (int i = 0; i < count; ++i) {
final ViewHolder holder = ...
...
final ItemHolderInfo animationInfo = mItemAnimator
.recordPreLayoutInformation(...);
mViewInfoStore.addToPreLayout(holder, animationInfo);
...
}
}
...
}
类ItemHolderInfo中封闭了对应ItemView的边界信息,即ItemView的left、top、right、bottom值。对象mViewInfoStore的作用正如源码注释:
/**
* Keeps data about views to be used for animations
*/
final ViewInfoStore mViewInfoStore = new ViewInfoStore();
再来看看addToPreLayout()方法:
void addToPreLayout(ViewHolder holder, ItemHolderInfo info) {
InfoRecord record = mLayoutHolderMap.get(holder);
if (record == null) {
record = InfoRecord.obtain();
mLayoutHolderMap.put(holder, recor