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

[Article] RecyclerView:pre_layout:Nu2

原创
作者头像
用户3702315
修改2021-03-04 17:50:31
4100
修改2021-03-04 17:50:31
举报
文章被收录于专栏:安卓开发
简介
  1. 在 RecyclerView 中存在一个叫 pre_layout 的阶段,与之对应的还有 real_layout、post_layout 的阶段。
  2. 其中 pre_layout 阶段的作用是记录数据集改变前的子控件信息(即动画开始前的控件位置信息),real_layout 是进行控件重新布局,post_layout阶段的作用是记录 real_layout 后的子控件位置信息及触发动画。
分析
代码语言:txt
复制
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 时都记录了什么内容:

代码语言:txt
复制
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 的作用正如源码注释:

代码语言:txt
复制
/**
  * Keeps data about views to be used for animations
  */
  final ViewInfoStore mViewInfoStore = new ViewInfoStore();

再来看看 addToPreLayout() 方法:

代码语言:txt
复制
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阶段:

代码语言:txt
复制
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() 方法:

代码语言:txt
复制
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 删除。

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