void dispatchLayout() {
...
if (mState.mLayoutStep == State.STEP_START) {
dispatchLayoutStep1();
...
dispatchLayoutStep2();
}
dispatchLayoutStep3();
...
}
方法 dispatchLayout() 会在 RecyclerView.onLayout() 中被调用,其中dispatchLayoutStep1() 就是 pre_layout,dispatchLayoutStep3() 就是post_layout,而 dispatchLayoutStep2() 自然就是处理真正测量和布局子视图(real_layout)。
首先来看看 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 中封闭了对应 ViewHolder 的边界信息,即 ViewHolder 的 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, record);
}
record.preInfo = info;
record.flags |= FLAG_PRE;
}
由上可已看出 RecyclerView 将 pre-layout 阶段的 ViewHolder 信息存放在 ViewInfoStore.mLayoutHolderMap 集合中。
接下来我们看看post_layout阶段:
private void dispatchLayoutStep3()
{
...
if(mState.mRunSimpleAnimations)
{
// Step 3: Find out where things are now, and process change animations.
...
for(int i = mChildHelper.getChildCount() - 1; i >= 0; i--)
{...
final ItemHolderInfo animationInfo = mItemAnimator.recordPostLayoutInformation(mState, holder);
...
if(...)
{
...
animateChange(oldChangeViewHolder, holder, preInfo, postInfo, oldDisappearing, newDisappearing);
}
else
{
mViewInfoStore.addToPostLayout(holder, animationInfo);
}
}
// Step 4: Process view info lists and trigger animations
mViewInfoStore.process(mViewInfoProcessCallback);
}
...
}
这是 addToPostLayout() 方法:
void addToPostLayout(ViewHolder holder, ItemHolderInfo info)
{
InfoRecord record = mLayoutHolderMap.get(holder);
if(record == null)
{
record = InfoRecord.obtain();
mLayoutHolderMap.put(holder, record);
}
record.postInfo = info;
record.flags |= FLAG_POST;
}
与 pre-layout 阶段相同,RecyclerView 也是将 post-layout 阶段的 ViewHolder 信息存放在 mViewInfoStore 的 mLayoutHolderMap 集合中,并且不难看出,同一个 ViewHolder 的 pre-layout 信息与 post-layout 信息封装在了同一个 InfoRecord 对象中,分别叫InfoRecord.preInfo 与 InforRecord.postInfo,这样 InfoRecord 就保存着同一个 ViewHolder 在数据集变化前后的信息,我们可以根据此信息定义动画的开始和结束状态。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。