跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

怎么让Android动画更流畅?GPU硬件加速全解析!

一、影响渲染流畅度的因素有哪些?

渲染流畅度,简单来说就是每帧渲染的时间。如果一帧渲染时间超过了屏幕刷新周期,就会出现掉帧,用户体验自然会大打折扣。

  • 系统渲染机制:Android为了保证线程安全和数据一致性,会将View的Measure、Layout、Draw等操作放在UI线程执行。当页面层级复杂时,这些操作会消耗大量时间,导致渲染卡顿。
  • CPU负载过高:软件渲染、多层级嵌套视图、频繁的重绘等都会导致CPU负载过高,从而影响渲染流畅度。
  • GPU负载过高:GPU渲染时过度绘制、大量复杂的绘制操作等都会导致GPU负载过高,从而影响渲染流畅度。
  • UIThread阻塞:UI线程负责处理用户输入、布局计算等操作。如果UI线程被阻塞,会导致界面卡顿、ANR。
  • 频繁/大量的纹理上传:Bitmap在Java/Native分配内存后,使用GPU渲染,需要进行纹理上传,频繁的纹理上传会导致卡顿。
  • 内存抖动:频繁的内存分配和回收会导致内存碎片增多,降低内存使用效率,频繁触发GC,导致卡顿。
  • 复杂的动画:复杂的动画效果需要进行大量的计算和绘制,如果优化不足,会导致动画卡顿。

二、GPU硬件加速源码分析

当Vsync信号到来时,Choreographer#onVsync会依次调用input、animator、traversal等回调。其中traversal终ViewRootImpl会依次执行performTraversals-->performDraw-->draw,进而在构建Displaylist并进行渲染。

渲染流程分为两部分:

  • UIThread上构建(重建/更新)DisplaylistOps
  • 把Displaylist同步到RenderThread线程,并调用GPU渲染管线(OpenGLES/Vulkan)进行渲染

三、使用RenderThread提升动画流畅度

动画可以分为基本的页面动画和复杂的动效。基本的页面动画用于按钮点击、页面切换、视图显示隐藏等常见的交互操作。动效指更复杂和有表现力的动画效果,涉及时间轴控制,矢量图动画等,通常使用渲染库(如:Lottie,libpag等)。

ViewPropertyAnimator对一些常见的属性(alpha、translation、scale、rorationo等)提供了GPU侧”变换“优化,由于属性动画不改变动画本身的绘制内容(背景、文本、位图等),只需要在CPU侧更新矩阵、属性等Displaylist信息,而不是重现生成整份Displaylist,避免频繁的在CPU上重跑measure/layout/draw,减少CPU端的大量工作, GPU使用这些更新后的参数进行最终的合成。

四、通过Perfetto进行效果对比

通过Perfetto对使用RenderThread对Animator进行加速和不使用RenderThread进行动画加速进行对比,可以很清晰的看到,使用RenderThread对Animator动画加速时,动画的计算和渲染都在RenderThread线程,完全解放了UIThread。

五、小结与拓展

本文介绍了GPU硬件加速在Android渲染中的作用,以及如何使用RenderThread提升动画流畅度。希望对大家有所帮助。

我是顺亿,来自趣航编程网(www.vqhf.com),一个专注于编程学习的平台。欢迎关注我们,一起学习成长。

相关文章