前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[Article] RecyclerView:pre_layout:Nu1

[Article] RecyclerView:pre_layout:Nu1

原创
作者头像
用户3702315
修改2021-03-03 18:01:45
4980
修改2021-03-03 18:01:45
举报
文章被收录于专栏:安卓开发
简介
  1. pre-layout 是为了 Item 动画而设计,在插入、删除的操作发生后(notifyItem*() 系列方法),先记录变化之前的Item位置信息(称为pre-layout);再执行重新测量和布局(real-layout);根据重新布局后记录变化后的 Item 位置信息并对比变化之前的 Item 位置信息执行动画(称为为post-layout)
  2. 如果不需要 pre-layout (即关闭Item动画功能),在LayoutManager.supportsPredictiveItemAnimations() 中返回 false 即可,这样给 RecyclerView 设置动画也不会有效果(Item直接生硬的显示出来)。
  3. 如果 supportsPredictiveItemAnimations() 返回true,则LayoutManager 中复写 onLayoutChildren() 会被调用2次:一次是在pre-layout,另一次是real-layout。
  4. pre-layout 对应 dispatchLayoutStep1(), real-layout 对应 dispatchLayoutStep2(),post-layout 对应 dispatchLayoutStep3(),这三个方法都在 onLayout() -> dispatchLayout() 中调用。
定义
代码语言:txt
复制
// RecyclerView的内部类
public static class State {
    ......
    boolean mInPreLayout = false;

    public boolean isPreLayout() {
        return mInPreLayout;
    }
    ......
}
赋值

第一处发生在 onMeasure()

代码语言:txt
复制
if (this.mState.mRunPredictiveAnimations) {
    this.mState.mInPreLayout = true;
} else {
    this.mAdapterHelper.consumeUpdatesInOnePass();
    this.mState.mInPreLayout = false;
}

第二处发生在 onLayout() -> dispatchLayout() -> dispatchLayoutStep1()

代码语言:txt
复制
mState.mInPreLayout = mState.mRunPredictiveAnimations;

上述两处都和 mRunPredictiveAnimations 挂钩,所以我们需要找到 mRunPredictiveAnimations 被赋值为 true 的时候

代码语言:txt
复制
// processAdapterUpdatesAndSetAnimationFlags() 有如下代码:

mState.mRunSimpleAnimations = mFirstLayoutComplete
    && mItemAnimator != null
    && (mDataSetHasChangedAfterLayout
    || animationTypeSupported
    || mLayout.mRequestedSimpleAnimations)
    && (!mDataSetHasChangedAfterLayout
    || mAdapter.hasStableIds());

mState.mRunPredictiveAnimations = mState.mRunSimpleAnimations
    && animationTypeSupported
    && !mDataSetHasChangedAfterLayout
    && predictiveItemAnimationsEnabled();

继续追溯 mRunSimpleAnimations,再追溯 mFirstLayoutComplete

代码语言:txt
复制
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    TraceCompat.beginSection(TRACE_ON_LAYOUT_TAG);
    dispatchLayout();
    TraceCompat.endSection();
    mFirstLayoutComplete = true;
}
总结
  1. 发现又回到了 onLayout(),但是我们在 dispatchLayout() 方法后才让mFirstLayoutComplete = true, 所以第一次 onLayout 的时候,肯定不会执行预布局。
  2. 所以我们明白了,pre-layout 并不是在第一次 measure 和 layout 前所存在的状态,而是在数据集发生变化的时候,所应该具有为 true 状态。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 定义
  • 赋值
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档