Animator源码

做百分比的定时更新,发现用Handler.postDelay会卡,同样的逻辑放到Animator里就不会。拜读一下Animator是怎么做的。
主要是四个类:Animator(基类)、ValueAnimator(主要分析)、ObjectAnimator和AnimatorSet。

Animator:

  • Animator是不做线程同步的,所有方法都是口头要求同线程操作。Handler的postDelay是有同步的,每次都会在MessageQueue.enqueueMessage时做同步
  • 所有listener都是顺序执行的,均在UI线程被调用
  • 清空listener时会 mListeners.clear(); mListeners = null;
  • 因为AnimatorListener的回调不是很全,又加入了AnimatorPauseListener,做到了向前兼容

ValueAnimator:

  • 主要逻辑是:AnimatorHandler(内部类,Runnable)持有当前线程(ThreadLocal实现)start的所有Animator。如果需要执行,AnimatorHandler将自己post到Choreographer中,在Choreographer收到页面刷新信息后回调自己,在其所在的Looper执行所有更新操作
  • a%b的语义是while(a>b) a -= b;float、double都是这个语义
  • 维持一些不变式,比如说startTime + fractionTime = now;会让程序简洁
  • 时间使用SystemClock.uptimeMillis()
  • Animator.setFrameDelay是直接给Choreographer设FrameDelay,不一定生效
  • 对于同一线程可能修改的容器,可以使用退化的CopyOnWrite策略
  • 不论在什么线程上启动,Animator的所有操作都在UI线程上执行,但是不同线程上启动的Animator之间的运行时间是不会互相影响的,相同线程的Animator会在同一队列顺序执行
  • 实际上Animator多出很多变量来减少中间计算,开发者没有这样做,很可能是为了减少维持不变式的成本,减少出错的概率

分析

之所以用Handler会卡,用Animator不卡,最重要的原因是Animator的间隔和时序都是通过Choreographer控制的,与页面刷新的节奏是同步的,而Handler可能会因为各种原因导致掉帧,看起来卡。为了保持Choreographer尽量的流程,增加的ThreadLocal区分不同的Animator。
使用不当(未及时remove listener,没有cancel Animator)可能有内存泄露。

你可能感兴趣的:(源码,android,动画)