美文网首页RecyclerView系列
RecyclerView的ItemAnimator源码浅析

RecyclerView的ItemAnimator源码浅析

作者: isLJli | 来源:发表于2020-12-20 22:12 被阅读0次

动画使用

 // 自定义ItemView的动画时间
      DefaultItemAnimator itemAnimator = new DefaultItemAnimator();
      //也可以不设置时间,使用默认时间
      itemAnimator.setAddDuration(1000);
      itemAnimator.setRemoveDuration(1000);
      itemAnimator.setChangeDuration(1000);
      itemAnimator.setMoveDuration(1000);
      recyclerView.setItemAnimator(itemAnimator);

动画调用
我们在平时更新Adapter的数据时会出现一会的白屏现象,这就是执行动画造成的。或者我们删除ItemView会有一个很小的时间差,这也是动画的效果。调用以下Adapter方法会触发ItemView的动画

      //会触动动画的更新
      adapter.notifyItemInserted(1);
      adapter.notifyItemRemoved(1);
      adapter.notifyItemChanged(1);
      adapter.notifyItemMoved(1, 2);

      // 不会触发动画的更新
      adapter.notifyDataSetChanged();

调用Adapternotify...(position)方法就可以执行动画,不过要写上特定的位置或位置区间。
在最后有一个更新notifyDataSetChanged是不会执行动画,原因是给ViewHolder设置了无效状态,在测量时就拿不到旧ViewHolder的信息,导致ItemView的动画不能执行。具体分析可以看上一篇RecyclerView的Adapter源码分析

动画源码
如果你不只是想自定义动画时间那么简单,而是想自己实现动画效果,那么最起码就要分析动画原来的源码。

public class RecyclerView extends ViewGroup implements ScrollingView,
    NestedScrollingChild2, NestedScrollingChild3 {
      // RecyclerView已经默认ItemAnimator的实例为DefaultItemAnimator
      ItemAnimator mItemAnimator = new DefaultItemAnimator();
}

//谷歌默认实现的动画类
public class DefaultItemAnimator extends SimpleItemAnimator { }
public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { }
public abstract static class ItemAnimator { }

RecyclerView的动画实现类是DefaultItemAnimator对象,而DefaultItemAnimator并不是直接继承RecyclerView.ItemAnimator,而是继承SimpleItemAnimator抽象类。SimpleItemAnimator抽象类才去继承RecyclerView.ItemAnimator

RecyclerView.ItemAnimator

RecyclerView.ItemAnimator源码除了实现了动画执行时间外,其他的大多数都是提供一个抽象方法让其子类实现。其中有五个抽象方法比较重要

animateDisappearance: View从可见区域到不可见区域,如View的删除-ReMove操作或滑动-Move操作到不可见区域
animateAppearance: View从不可见区域到可见区域,如View的增加-Add操作或滑动-Move操作到可见区域
animateChange:View的更新操作
animatePersistence:此方法的调用时机是ItemView未进行任何操作。
runPendingAnimations:开始执行动画方法

继承RecyclerView.ItemAnimator需要重写什么方法?

public class SimplesItemAnimator extends RecyclerView.ItemAnimator {

  // View从可见区域到不可见区域,如View的删除ReMove操作或滑动Move操作到不可见区域
  @Override
  public boolean animateDisappearance(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull ItemHolderInfo preLayoutInfo, @Nullable ItemHolderInfo postLayoutInfo) {
      return false;
  }

  // View从不可见区域到可见区域,如View的增加Add操作或滑动Move操作到可见区域
  @Override
  public boolean animateAppearance(@NonNull RecyclerView.ViewHolder viewHolder, @Nullable ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
      return false;
  }

  // 此方法的调用时机是ItemView未进行任何操作。
  @Override
  public boolean animatePersistence(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
      return false;
  }

  // View的更新操作
  @Override
  public boolean animateChange(@NonNull RecyclerView.ViewHolder oldHolder, @NonNull RecyclerView.ViewHolder newHolder, @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
      return false;
  }

  // 开始执行动画操作
  @Override
  public void runPendingAnimations() {

  }

  // 结束ViewHolder的动画
  @Override
  public void endAnimation(@NonNull RecyclerView.ViewHolder item) {

  }

  // 结束动画
  @Override
  public void endAnimations() {

  }

  // 是否在运行
  @Override
  public boolean isRunning() {
      return false;
  }
}

重写的方法好挺多,接下来看看谷歌提供的实例是如何重写的。

SimpleItemAnimtor

其中SimpleItemAnimtor就是谷歌实现的继承RecyclerView.ItemAnimator的类,我们看看它是如何实现抽象方法的。

public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {

private static final boolean DEBUG = false;

private static final String TAG = "SimpleItemAnimator";

boolean mSupportsChangeAnimations = true;

@SuppressWarnings("unused")
public boolean getSupportsChangeAnimations() {
    return mSupportsChangeAnimations;
}


public void setSupportsChangeAnimations(boolean supportsChangeAnimations) {
    mSupportsChangeAnimations = supportsChangeAnimations;
}

@Override
public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
    return !mSupportsChangeAnimations || viewHolder.isInvalid();
}

// 判断新旧的左上位置是否相同,不相同执行Move动画,相同执行ReMove动画
@Override
public boolean animateDisappearance(@NonNull RecyclerView.ViewHolder viewHolder,
        @NonNull ItemHolderInfo preLayoutInfo, @Nullable ItemHolderInfo postLayoutInfo) {
    int oldLeft = preLayoutInfo.left;
    int oldTop = preLayoutInfo.top;
    View disappearingItemView = viewHolder.itemView;
    int newLeft = postLayoutInfo == null ? disappearingItemView.getLeft() : postLayoutInfo.left;
    int newTop = postLayoutInfo == null ? disappearingItemView.getTop() : postLayoutInfo.top;
   // !isRemoved() 和 新旧的 左或上位置不相同 
    if (!viewHolder.isRemoved() && (oldLeft != newLeft || oldTop != newTop)) {
        disappearingItemView.layout(newLeft, newTop,
                newLeft + disappearingItemView.getWidth(),
                newTop + disappearingItemView.getHeight());
        if (DEBUG) {
            Log.d(TAG, "DISAPPEARING: " + viewHolder + " with view " + disappearingItemView);
        }
        // 调用移动抽象方法
        return animateMove(viewHolder, oldLeft, oldTop, newLeft, newTop);
    } else {
        if (DEBUG) {
            Log.d(TAG, "REMOVED: " + viewHolder + " with view " + disappearingItemView);
        }
       // 调用删除抽象方法
        return animateRemove(viewHolder);
    }
}

 // 判断新旧的viewHolder的左上位置是否相同,不相同执行move动画,相同执行Add动画
@Override
public boolean animateAppearance(@NonNull RecyclerView.ViewHolder viewHolder,
        @Nullable ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
    // preLayoutInfo位置信息不null 和 新旧的 左或上位置不相同
    if (preLayoutInfo != null && (preLayoutInfo.left != postLayoutInfo.left
            || preLayoutInfo.top != postLayoutInfo.top)) {
        // slide items in if before/after locations differ
        if (DEBUG) {
            Log.d(TAG, "APPEARING: " + viewHolder + " with view " + viewHolder);
        }
        // 调用移动抽象方法
        return animateMove(viewHolder, preLayoutInfo.left, preLayoutInfo.top,
                postLayoutInfo.left, postLayoutInfo.top);
    } else {
        if (DEBUG) {
            Log.d(TAG, "ADDED: " + viewHolder + " with view " + viewHolder);
        }
         // 调用增加抽象方法
        return animateAdd(viewHolder);
    }
}

 // 如果新旧Viewholder的左上位置不相同执行Move动画,相同则结束动画
@Override
public boolean animatePersistence(@NonNull RecyclerView.ViewHolder viewHolder,
        @NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) {
     // 新旧的 左或上位置不相同
    if (preInfo.left != postInfo.left || preInfo.top != postInfo.top) {
        if (DEBUG) {
            Log.d(TAG, "PERSISTENT: " + viewHolder
                    + " with view " + viewHolder.itemView);
        }
        // 调用移动抽象方法
        return animateMove(viewHolder,
                preInfo.left, preInfo.top, postInfo.left, postInfo.top);
    }
    // 结束viewHolder的动画
    dispatchMoveFinished(viewHolder);
    return false;
}

// 执行Change动画
@Override
public boolean animateChange(@NonNull RecyclerView.ViewHolder oldHolder, @NonNull RecyclerView.ViewHolder newHolder,
        @NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) {
    if (DEBUG) {
        Log.d(TAG, "CHANGED: " + oldHolder + " with view " + oldHolder.itemView);
    }
    final int fromLeft = preInfo.left;
    final int fromTop = preInfo.top;
    final int toLeft, toTop;
    // 设置toLeft, toTop的值
    if (newHolder.shouldIgnore()) {
        // newHolder应该忽略,则使用旧ViewHolder的位置
        toLeft = preInfo.left;
        toTop = preInfo.top;
    } else {
       // 否则使用新ViewHolder的位置
        toLeft = postInfo.left;
        toTop = postInfo.top;
    }
    // 调用更新的抽象方法
    return animateChange(oldHolder, newHolder, fromLeft, fromTop, toLeft, toTop);
}

// -> 提供了Remove抽象方法
public abstract boolean animateRemove(RecyclerView.ViewHolder holder);
// -> 提供了Add抽象方法
public abstract boolean animateAdd(RecyclerView.ViewHolder holder);
// -> 提供了Move抽象方法
public abstract boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY,
        int toX, int toY);
// -> 提供了Change抽象方法
public abstract boolean animateChange(RecyclerView.ViewHolder oldHolder,
        RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop);


// ->    dispatchAnimationFinished真正实现关闭的方法,其他方法只是对外提供开始结束的方法
public final void dispatchRemoveFinished(RecyclerView.ViewHolder item) {
    onRemoveFinished(item);
    dispatchAnimationFinished(item);
}

//... 省略一些动画开始结束的调用的方法,是提供给外部扩展的空方法。
}

SimpleItemAnimator类中,主要重写了ItemAnimtoranimate...系列方法,并在这个方法中根据新旧ViewHolderLefttop的位置是否相等来判断ItemView的状态,并根据ItemView要执行的操作分别调用animateRemove,animateAdd ,animateMove ,animateChange抽象方法。

DefaultItemAnimator

DefaultItemAnimator就是继承SimpleItemAnimator实现动画的最终执行效果,所以我们在自定义的时候也可以通过继承SimpleItemAnimator实现动画的最终效果。

public class DefaultItemAnimator extends SimpleItemAnimator {
  private static final boolean DEBUG = false;

  private static TimeInterpolator sDefaultInterpolator;

  // 装置全部动画的ViewHolder的相关信息集合
  private ArrayList<RecyclerView.ViewHolder> mPendingRemovals = new ArrayList<>();
  private ArrayList<RecyclerView.ViewHolder> mPendingAdditions = new ArrayList<>();
  private ArrayList<MoveInfo> mPendingMoves = new ArrayList<>();
  private ArrayList<ChangeInfo> mPendingChanges = new ArrayList<>();

  // 将一种类型的执行动画开始前的ViewHolder集合装进来,集合动画结束后再移除掉
  ArrayList<ArrayList<RecyclerView.ViewHolder>> mAdditionsList = new ArrayList<>();
  ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<>();
  ArrayList<ArrayList<ChangeInfo>> mChangesList = new ArrayList<>();

  // 将ViewHolder执行动画前装进来,动画执行后移除
  ArrayList<RecyclerView.ViewHolder> mAddAnimations = new ArrayList<>();
  ArrayList<RecyclerView.ViewHolder> mMoveAnimations = new ArrayList<>();
  ArrayList<RecyclerView.ViewHolder> mRemoveAnimations = new ArrayList<>();
  ArrayList<RecyclerView.ViewHolder> mChangeAnimations = new ArrayList<>();

  // 因为移动move复杂,Viewholder和位置信息封装成一个类
  private static class MoveInfo {
      public RecyclerView.ViewHolder holder;
      public int fromX, fromY, toX, toY;

      MoveInfo(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
          this.holder = holder;
          this.fromX = fromX;
          this.fromY = fromY;
          this.toX = toX;
          this.toY = toY;
      }
  }

  // 因为change更新操作复杂,新旧ViewHolder和位置信息封装成一个类
  private static class ChangeInfo {
      public RecyclerView.ViewHolder oldHolder, newHolder;
      public int fromX, fromY, toX, toY;
      private ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder) {
          this.oldHolder = oldHolder;
          this.newHolder = newHolder;
      }

      ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder,
              int fromX, int fromY, int toX, int toY) {
          this(oldHolder, newHolder);
          this.fromX = fromX;
          this.fromY = fromY;
          this.toX = toX;
          this.toY = toY;
      }

      @Override
      public String toString() {
          return "ChangeInfo{"
                  + "oldHolder=" + oldHolder
                  + ", newHolder=" + newHolder
                  + ", fromX=" + fromX
                  + ", fromY=" + fromY
                  + ", toX=" + toX
                  + ", toY=" + toY
                  + '}';
      }
  }

  @Override
  public boolean animateRemove(final RecyclerView.ViewHolder holder) {
      resetAnimation(holder); //为view设置差值器,结束holder的动画
      mPendingRemovals.add(holder); // 增加一个holder到删除集合
      return true;
  }
  // 真正执行移除remove动画的方法
  private void animateRemoveImpl(final RecyclerView.ViewHolder holder) {
      final View view = holder.itemView;
      final ViewPropertyAnimator animation = view.animate();
      mRemoveAnimations.add(holder); // 动画开始前将holder增加进mRemoveAnimations集合
      // 为动画设置时间,并把透明度设置为1-0,设置动画监听
      animation.setDuration(getRemoveDuration()).alpha(0).setListener(
              new AnimatorListenerAdapter() {
                  @Override
                  public void onAnimationStart(Animator animator) {
                      dispatchRemoveStarting(holder); // 向外提供的接口,此方法什么也没做
                  }

                  @Override
                  public void onAnimationEnd(Animator animator) {
                     // 动画结束后置空监听
                      animation.setListener(null);
                      view.setAlpha(1); //透明度设置为1
                      dispatchRemoveFinished(holder); //结束动画,并向外提供方法
                      mRemoveAnimations.remove(holder); //移除相关holder
                      dispatchFinishedWhenDone();
                  }
              }).start();
  }

  // 增加add动画
  @Override
  public boolean animateAdd(final RecyclerView.ViewHolder holder) {
      resetAnimation(holder); //为view设置差值器,结束holder的动画
      holder.itemView.setAlpha(0); //设置透明度为0
      mPendingAdditions.add(holder);//增加holder到mPendingAdditions集合中
      return true;
  }
  // 执行增加add动画的真正方法
  void animateAddImpl(final RecyclerView.ViewHolder holder) {
      final View view = holder.itemView;
      final ViewPropertyAnimator animation = view.animate();
      mAddAnimations.add(holder); // 增加holder到mAddAnimations集合中
      // 设置动画时间和透明度最后为0-1
      animation.alpha(1).setDuration(getAddDuration())
              .setListener(new AnimatorListenerAdapter() {
                  @Override
                  public void onAnimationStart(Animator animator) {
                      dispatchAddStarting(holder);
                  }

                  @Override
                  public void onAnimationCancel(Animator animator) {
                      view.setAlpha(1);
                  }

                  @Override
                  public void onAnimationEnd(Animator animator) {
                      animation.setListener(null);  // 监听置空
                      dispatchAddFinished(holder);  
                      mAddAnimations.remove(holder);
                      dispatchFinishedWhenDone();
                  }
              }).start();
  }

  // 移动move动画
  @Override
  public boolean animateMove(final RecyclerView.ViewHolder holder, int fromX, int fromY,
          int toX, int toY) {
      final View view = holder.itemView;
      //  fromX加上移动的距离
      fromX += (int) holder.itemView.getTranslationX();
      fromY += (int) holder.itemView.getTranslationY();
      resetAnimation(holder);
      int deltaX = toX - fromX;
      int deltaY = toY - fromY;
      //deltaX==0表示移动完成 
      if (deltaX == 0 && deltaY == 0) {
          dispatchMoveFinished(holder);
          return false;
      }
      // 设置还没移动完的距离
      if (deltaX != 0) {
          view.setTranslationX(-deltaX);
      }
      if (deltaY != 0) {
          view.setTranslationY(-deltaY);
      }
       // 真正集合中添加
      mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY));
      return true;
  }
 // 执行移动move动画的真正方法
  void animateMoveImpl(final RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
      final View view = holder.itemView;
      final int deltaX = toX - fromX;
      final int deltaY = toY - fromY;
      if (deltaX != 0) {
          view.animate().translationX(0);
      }
      if (deltaY != 0) {
          view.animate().translationY(0);
      }
      // TODO: make EndActions end listeners instead, since end actions aren't called when
      // vpas are canceled (and can't end them. why?)
      // need listener functionality in VPACompat for this. Ick.
      final ViewPropertyAnimator animation = view.animate();
      mMoveAnimations.add(holder);
     // 设置动画执行的时间与距离 -deltaX-0
      animation.setDuration(getMoveDuration()).setListener(new AnimatorListenerAdapter() {
          @Override
          public void onAnimationStart(Animator animator) {
              dispatchMoveStarting(holder);
          }

          @Override
          public void onAnimationCancel(Animator animator) {
              if (deltaX != 0) {
                  view.setTranslationX(0);
              }
              if (deltaY != 0) {
                  view.setTranslationY(0);
              }
          }

          @Override
          public void onAnimationEnd(Animator animator) {
              animation.setListener(null);
              dispatchMoveFinished(holder);
              mMoveAnimations.remove(holder);
              dispatchFinishedWhenDone();
          }
      }).start();
  }

  @Override
  public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder,
          int fromX, int fromY, int toX, int toY) {
      // 如果旧ViewHolder与新ViewHolder相等,则给Move动画
      if (oldHolder == newHolder) {
          // Don't know how to run change animations when the same view holder is re-used.
          // run a move animation to handle position changes.
          return animateMove(oldHolder, fromX, fromY, toX, toY);
      }
      // 旧ViewHolder的位移和透明度
      final float prevTranslationX = oldHolder.itemView.getTranslationX();
      final float prevTranslationY = oldHolder.itemView.getTranslationY();
      final float prevAlpha = oldHolder.itemView.getAlpha();
      resetAnimation(oldHolder);
      // 差值
      int deltaX = (int) (toX - fromX - prevTranslationX);
      int deltaY = (int) (toY - fromY - prevTranslationY);
      // recover prev translation state after ending animation
     // 给旧ViewHolder设置之前的位移和透明度
      oldHolder.itemView.setTranslationX(prevTranslationX);
      oldHolder.itemView.setTranslationY(prevTranslationY);
      oldHolder.itemView.setAlpha(prevAlpha);
       // 给新的Viewholder设置差值和透明度
      if (newHolder != null) {
          // carry over translation values
          resetAnimation(newHolder);
          newHolder.itemView.setTranslationX(-deltaX);
          newHolder.itemView.setTranslationY(-deltaY);
          newHolder.itemView.setAlpha(0);
      }
      mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY));
      return true;
  }

  void animateChangeImpl(final ChangeInfo changeInfo) {
      final RecyclerView.ViewHolder holder = changeInfo.oldHolder;
      final View view = holder == null ? null : holder.itemView;
      final RecyclerView.ViewHolder newHolder = changeInfo.newHolder;
      final View newView = newHolder != null ? newHolder.itemView : null;
      if (view != null) {
          final ViewPropertyAnimator oldViewAnim = view.animate().setDuration(
                  getChangeDuration());
          mChangeAnimations.add(changeInfo.oldHolder);
          oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX);
          oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY);
          oldViewAnim.alpha(0).setListener(new AnimatorListenerAdapter() {
              @Override
              public void onAnimationStart(Animator animator) {
                  dispatchChangeStarting(changeInfo.oldHolder, true);
              }

              @Override
              public void onAnimationEnd(Animator animator) {
                  oldViewAnim.setListener(null);
                  view.setAlpha(1);
                  view.setTranslationX(0);
                  view.setTranslationY(0);
                  dispatchChangeFinished(changeInfo.oldHolder, true);
                  mChangeAnimations.remove(changeInfo.oldHolder);
                  dispatchFinishedWhenDone();
              }
          }).start();
      }
      if (newView != null) {
          final ViewPropertyAnimator newViewAnimation = newView.animate();
          mChangeAnimations.add(changeInfo.newHolder);
          newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration())
                  .alpha(1).setListener(new AnimatorListenerAdapter() {
                      @Override
                      public void onAnimationStart(Animator animator) {
                          dispatchChangeStarting(changeInfo.newHolder, false);
                      }
                      @Override
                      public void onAnimationEnd(Animator animator) {
                          newViewAnimation.setListener(null);
                          newView.setAlpha(1);
                          newView.setTranslationX(0);
                          newView.setTranslationY(0);
                          dispatchChangeFinished(changeInfo.newHolder, false);
                          mChangeAnimations.remove(changeInfo.newHolder);
                          dispatchFinishedWhenDone();
                      }
                  }).start();
      }
  }

 // 开始执行动画
  @Override
  public void runPendingAnimations() {
      // 先将集合检查一遍,都为空的话就不执行动画了。
      boolean removalsPending = !mPendingRemovals.isEmpty();
      boolean movesPending = !mPendingMoves.isEmpty();
      boolean changesPending = !mPendingChanges.isEmpty();
      boolean additionsPending = !mPendingAdditions.isEmpty();
      if (!removalsPending && !movesPending && !additionsPending && !changesPending) {
          // nothing to animate
          return;
      }
      // First, remove stuff  首先,执行删除ReMove动画集合
      for (RecyclerView.ViewHolder holder : mPendingRemovals) {
         // 真正执行remove动画的在animateRemoveImpl方法
          animateRemoveImpl(holder);
      }
      mPendingRemovals.clear(); //动画完毕后,清空集合
      // Next, move stuff 第二是执行移动动画
      if (movesPending) {
          final ArrayList<MoveInfo> moves = new ArrayList<>();
          moves.addAll(mPendingMoves); //临时变量装move动画集合
          mMovesList.add(moves); // 装载move动画集合
          mPendingMoves.clear(); // 真正集合被清空了
          Runnable mover = new Runnable() {
              @Override
              public void run() {
                  for (MoveInfo moveInfo : moves) {
                      // 真正执行move动画是animateMoveImpl方法
                      animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY,
                              moveInfo.toX, moveInfo.toY);
                  }
                  moves.clear(); //动画执行后,临时变量被清空
                  mMovesList.remove(moves); //动画执行后,mMovesList移除集合
              }
          };
          //如果有删除动画,则等到remove动画执行完,才开始执行移动动画。
          if (removalsPending) {
              View view = moves.get(0).holder.itemView;
              ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration());
          } else {
              mover.run();
          }
      }
      // Next, change stuff, to run in parallel with move animations
      // 第三步,执行更新change的动画集合
      if (changesPending) {
          // 临时变量
          final ArrayList<ChangeInfo> changes = new ArrayList<>();
          changes.addAll(mPendingChanges);
          mChangesList.add(changes); //动画集合开始前装到mChangesList
          mPendingChanges.clear(); // 真正集合清空
          Runnable changer = new Runnable() {
              @Override
              public void run() {
                  for (ChangeInfo change : changes) {
                      // 真正执行change动画方法animateChangeImpl
                      animateChangeImpl(change);
                  }
                  changes.clear(); // 动画集合执行完后,清空临时变量
                  mChangesList.remove(changes);// 动画集合执行完后,mChangesList清除相关集合
              }
          };
          // 如果有删除动画,则等动画执行后,才调用异步run方法
          if (removalsPending) {
              RecyclerView.ViewHolder holder = changes.get(0).oldHolder;
              ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration());
          } else {
              changer.run();
          }
      }
      // Next, add stuff  最后一步,增加add操作动画
      if (additionsPending) {
          // 临时变量集合
          final ArrayList<RecyclerView.ViewHolder> additions = new ArrayList<>();
          additions.addAll(mPendingAdditions);
          mAdditionsList.add(additions); //集合执行之前,装进mAdditionsList
          mPendingAdditions.clear(); // 清空真正集合
          Runnable adder = new Runnable() {
              @Override
              public void run() {
                  for (RecyclerView.ViewHolder holder : additions) {
                     // 真正执行增加的动画方法
                      animateAddImpl(holder);
                  }
                  additions.clear();
                  mAdditionsList.remove(additions);
              }
          };
          // add操作动画要在移除和移动更新动画执行完后才执行
          if (removalsPending || movesPending || changesPending) {
              long removeDuration = removalsPending ? getRemoveDuration() : 0;
              long moveDuration = movesPending ? getMoveDuration() : 0;
              long changeDuration = changesPending ? getChangeDuration() : 0;
              long totalDelay = removeDuration + Math.max(moveDuration, changeDuration);
              View view = additions.get(0).itemView;
              ViewCompat.postOnAnimationDelayed(view, adder, totalDelay);
          } else {
              adder.run();
          }
      }
  }

相关文章

网友评论

    本文标题:RecyclerView的ItemAnimator源码浅析

    本文链接:https://www.haomeiwen.com/subject/vuziwktx.html