美文网首页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