Android中的动画使用注意事项
基本上现如今市面上所有的app,都会使用到动画效果,动画可以很好的提升用户的交互体验。
Android中的动画大概可以分成两个发展阶段:在Android3.0之前,Framework层提供了android.view.animation,可以实现View,ViewGroup的各种动画效果,比如AlphaAnimation,RotateAnimation,ScaleAnimation,TranslateAnimation,就可以分别实现透明度,旋转,缩放,位移等动画效果。当然,也可以通过AnimationSet将多个动画联合使用,以达到更复杂的效果。
为什么在Android3.0之后,就不推荐使用animation的动画了呢,是因为它大概有以下几点缺点:
- animation的动画,只能实现View的简单的动画效果,复杂的,比如颜色过渡无法实现;
- animation只能操作View及其子类的可视化动画效果,但是,有可能一些非view类型的随时间轴变化的效果无法实现(layout,position的变化);
- animation只是简单的将view的视图信息发生了改变以达到视觉上的动画效果,但是view自身的属性没有发生根本的变化。
为了弥补以上的缺点和不足,在Android3.0以上,Framework又提供了另一套动画框架:android.animation.animator。
- Animation在动画实现的机制上与Animator是完全不同的。一句话概括就是:Animation实在每次绘制之前,通过将整块画布矩阵变换,从而实现视觉坐标系的移动、变换,但实际上其view内部记录的坐标信息以及其他属性始终没有发生变化。
- Animator其实在动画实现上更加直接,简单一些。他是计算动画节点上对应的value,然后将此value通过不同的方式作用到view的属性参数上。(以下会有更详细的Animator机制的介绍)
两者的优劣对比:
- 版本兼容性:Animation全版本支持。Animator只能支持Android3.0以上。
- 使用范围:Animation只能操作view。Animator不仅支持view动画,还可以操作多种属性的变化,任何实现相关方法的对象,都可以使用Animator来达到属性变化的过程。
- 实现效率:Animation通过画布矩阵变换处理view的动画效果。Animator则是通过对象属性set,get方法的反射调用,来达到所操作对象相关属性的变化的。因此,从效率上来说,Animation的效率可能稍高一些,而Animator由于在动画过程中要使用反射,效率稍差一些。
- 使用效果:Animation因为只是画布的矩阵变化,view的属性,位置信息并没有发生变化,所以,动画之后view的点击事件等处理都会非常麻烦。Animator因为是直接操作view的属性,在做动画的同时,view的属性也相应的发生了变化,所以不用担心view的属性与视觉上不一致的问题。
随着Android系统版本不断的提升,使用3.0以下系统的手机将会越来越少,时间效率。所以也就没有必要单独去深入源码分析Animation的实现原理了。而Animator是高版本一直支持的框架,因此,着重分析一下在可预见的很长一段时间内Android一直会使用的Animator的实现原理吧。
1,继承关系
2, Animator的工作流程
1,ObjectAnimator.ofXXX(Object target, String propertyName, TYPE… values)
|
|
setDuration等省略
2,ObjectAnimator.start()
|
|
3,AnimationHandler.addAnimationFrameCallback()
|
|
4.Choreographer.postFrameCallback()
|
|
5. AnimationHandler.mFrameCallback
4步骤中,此刻token == FRAME_CALLBACK_TOKEN,执行if中的动作,调用的就是AnimationHandler中定义的Choreographer.FrameCallback:上面已经说过,但是上述中省略了最重要的一步:
6. ValueAnimator.doAnimationFrame
5步骤中callback为AnimationFrameCallback,ValueAnimator实现此接口,因此是调用的ValueAnimator中的doAnimationFrame:
7.循环流程,直到timeout
以上步骤为一个动画在一帧中的完整流程,只要动画尚未完成,Animator就不会将自己从AnimationHandler中的监听List中删除,则Choreography.FrameCallback就会持续的注册,监听回调完成后续帧中动画变化。
3, 小结:
- 使用多个Animator,AnimatorSet,或者PropertyValueHolder在性能上并没有明显的差异,他们之间的关系大体如下所示:
注意到:总体调用对象的次数没有发生变化。
- 如果多个Animator都是操作同一个View的UI属性,则在每一个PropertyValueHolder每次被更新并调用View对应的方法时,就会多次调用view.invalidate和requestlayout方法。这样就会执行很多次非必要的方法,这是就可以考虑使用ViewPropertyAnimator:12textview.animate().x(500).y(500).setDuration(5000).setInterpolator(new BounceInterpolator());ViewPropertyAnimator不能直接创建实例对象,只能通过view.animate()来获得针对此View的实例。
通过查看ViewPropertyAnimator的实现,其实在其内部也是使用的ValueAnimator来实现的view的动画效果,但是呢,ViewPropertyAnimator针对多个Animator调用时的缺点,进行了优化,以提高性能(将需要使用动画的属性,放到一个Map里面,等待下一次的帧更新动作,然后在帧更新时,使用View内部存储的RenderNode节点,将各个属性值设置上去,然后调用View.invalidateViewProperty()(简化版的invalidate操作));
此处可结合在搜狗浏览器V4.5优化网页加载进度条动画效果在天猫等个别重定向甚多的网站时,由于错误的使用ValueAnimator造成invalidate,requestlayout调用次数太多,从而影响了MainHandler其他message的及时响应,造成ANR的问题。。。
但是使用中应该注意,ViewPropertyAnimator不能在外部持有其实例,以便以后反复使用,必须每次通过View.animate来获得实例。
- 接下来就要分析一下在支持硬件加速的机器上,针对动画开启硬件加速的一些功能。