Android RecyclerView 动画处理 流程 原理(源码分析第二篇)

零、本文主题

本文要解决的问题:
1. Recyclerview 动画的实现原理是什么?
2. 处理的主要流程大概是怎样的?

一、核心原理

我们抛开代码,想一下,RecyclerView中的view动画有几种?
添加一个view:添加的View 显示出来,它下面的所有view向下移动一格距离
删除一个view:删除的View 渐隐掉,它下面的所有view向上移动一格距离
上下滑动:所有子view上下滑动
移动:…

归纳起来,最终实现动画的时候,无外乎会执行几个操作:
添加或删除View的 透明度动画 0->1 或 1->0
子view的y轴坐标,由动画前的位置,滑动到 动画后的位置(我们暂时只讨论常见的竖向布局)

所以,看似复杂的RecyclerView动画处理,经过分解后,其实就是一个view的简单动画,没有任何新奇的玩意或算法。

所有需要做的就是,记录下动画执行前view的状态(透明度,y坐标),以及计算出动画的目的地(透明度,y坐标),然后执行动画,仅此而已,这就是RecyclerView动画实现的核心原理。

二、源码分析 - 主流程

经过上面的分析,其实我们的重点变成了,view数据的组织与记录(动画前),view的数据的计算(动画后),心里要有这个数。
然后,我们大概看一下,整个流程:

2.1 最终执行动画的

核心接口:RecyclerView.ItemAnimator
核心实现类:DefaultItemAnimator
核心实现方法:DefaultItemAnimator.runPendingAnimations()

调用栈如下:
DefaultItemAnimator.runPendingAnimations() — 核心方法
|
RecyclerView.mItemAnimatorRunner
|
RecyclerView.postAnimationRunner()
|
ViewInfoStore.ProcessCallback
|
ViewInfoStore.process(ProcessCallback callback)
|
RecyclerView.dispatchLayoutStep3() 触发动画的根

=== RecyclerView.java
private void dispatchLayoutStep3() {
	......
 	// Step 4: Process view info lists and trigger animations
    mViewInfoStore.process(mViewInfoProcessCallback);
}

2.2 动画信息存储

核心类:ViewInfoStore
核心数据结构:mLayoutHolderMap

final SimpleArrayMap<RecyclerView.ViewHolder, InfoRecord> mLayoutHolderMap =
            new SimpleArrayMap<>();

ViewInfoStore这个类,抽象了所有的子View的(为了运行动画的)跟踪信息。
看下mLayoutHolderMap,ViewHolder就是子view,映射了一个InfoRecord

static class InfoRecord {
        @Nullable
        RecyclerView.ItemAnimator.ItemHolderInfo preInfo;
        @Nullable
        RecyclerView.ItemAnimator.ItemHolderInfo postInfo;

一目了然,preInfo是动画执行前的信息,postInfo是动画执行后的信息。

public static class ItemHolderInfo {
            public int left;
            public int top;
            public int right;
            public int bottom;
            public int changeFlags;

ItemHolderInfo 记录了View的坐标与flag。
推断逻辑:
也就是说在2.1最终执行动画前,ViewInfoStore中的数据应该是已经准备好的。

2.3 动画执行前,view信息保存

核心类:ViewInfoStore
核心方法:addToPreLayout()
入口:RecyclerView.dispatchLayoutStep1()

final ItemHolderInfo animationInfo = mItemAnimator
                        .recordPreLayoutInformation(mState, holder,
                                ItemAnimator.buildAdapterChangeFlagsForAnimations(holder),
                                holder.getUnmodifiedPayloads());
                mViewInfoStore.addToPreLayout(holder, animationInfo);

2.4 计算“动画执行后,View应该要处于的状态”的信息

核心类:ViewInfoStore
核心方法:addToPostLayout()
入口:RecyclerView.dispatchLayoutStep3()

final ItemHolderInfo animationInfo = mItemAnimator
                        .recordPostLayoutInformation(mState, holder);
......
mViewInfoStore.addToPostLayout(holder, animationInfo);

以上,就是本篇的主要内容了。


以后有时间的话,补一下细节流程,再更新吧。
/// 三、源码分析 - 细节流程分析