前面博客分析了导致app卡顿慢的直接原因,这里就从原因出发,分析一些优化方案(这里主要是从直接影响渲染机制的布局相关进行分析)

1) Invalidations, Layouts, and Performance(动画,布局的优化)

顺滑精妙的动画是app设计里面最重要的元素之一,这些动画能够显著提升用户体验。下面会讲解Android系统是如何处理UI组件的更新操作的。

通常来说,Android需要把XML布局文件转换成GPU能够识别并绘制的对象。这个操作是在DisplayList的帮助下完成的。DisplayList持有所有将要交给GPU绘制到屏幕上的数据信息。

在某个View第一次需要被渲染时,DisplayList会因此而被创建,当这个View要显示到屏幕上时,我们会执行GPU的绘制指令来进行渲染。如果你在后续有执行类似移动这个View的位置等操作而需要再次渲染这个View时,我们就仅仅需要额外操作一次渲染指令就够了。然而如果你修改了View中的某些可见组件,那么之前的DisplayList就无法继续使用了,我们需要回头重新创建一个DisplayList并且重新执行渲染指令并更新到屏幕上。

需要注意的是:任何时候View中的绘制内容发生变化时,都会重新执行创建DisplayList,渲染DisplayList,更新到屏幕上等一系列操作。这个流程的表现性能取决于你的View的复杂程度,View的状态变化以及渲染管道的执行性能。举个例子,假设某个Button的大小需要增大到目前的两倍,在增大Button大小之前,需要通过父View重新计算并摆放其他子View的位置。修改View的大小会触发整个HierarcyView的重新计算大小的操作(特别是绘制动画时影响是很严重的)。如果是修改View的位置则会触发HierarchView重新计算其他View的位置。如果布局很复杂,这就会很容易导致严重的性能问题。我们需要尽量减少Overdraw。

我们可以通过前面介绍的Monitor GPU Rendering来查看渲染的表现性能如何,另外也可以通过开发者选项里面的Show GPU view updates来查看视图更新的操作,最后我们还可以通过HierarchyViewer这个工具来查看布局,使得布局尽量扁平化(层数尽量减少),移除非必需的UI组件,这些操作能够减少Measure,Layout的计算时间,制作动画时,运动元素与其父控件的关系要好好考虑,尽量在运动元素运动过程中,不会导致其父控件变化,否则就会导致父控件重绘,整个重绘可能影响到整个布局文件,这就是你做出的动画卡顿慢的可能原因之一。

2) Overdraw, Cliprect, QuickReject(过度绘制)

引起性能问题的一个很重要的方面是因为过多复杂的绘制操作。我们可以通过工具来检测并修复标准UI组件的Overdraw问题,但是针对高度自定义的UI组件则显得有些力不从心。

有一个窍门是我们可以通过执行几个APIs方法来显著提升绘制操作的性能。前面有提到过,非可见的UI组件进行绘制更新会导致Overdraw。例如Nav Drawer从前置可见的Activity滑出之后,如果还继续绘制那些在Nav Drawer里面不可见的UI组件,这就导致了Overdraw。为了解决这个问题,Android系统会通过避免绘制那些完全不可见的组件来尽量减少Overdraw。那些Nav Drawer里面不可见的View就不会被执行浪费资源(对于不需要用户看见的元素,设置属性为gone,这可以在一定程度上优化性能,这时与设置成invisable相比较的)。

但是不幸的是,对于那些过于复杂的自定义的View(重写了onDraw方法),Android系统无法检测具体在onDraw里面会执行什么操作,系统无法监控并自动优化,也就无法避免Overdraw了。但是我们可以通过canvas.clipRect()来帮助系统识别那些可见的区域。这个方法可以指定一块矩形区域,只有在这个区域内才会被绘制,其他的区域会被忽视。这个API可以很好的帮助那些有多组重叠组件的自定义View来控制显示的区域。同时clipRect方法还可以帮助节约CPU与GPU资源,在clipRect区域之外的绘制指令都不会被执行,那些部分内容在矩形区域内的组件,仍然会得到绘制。

除了clipRect方法之外,我们还可以使用canvas.quickreject()来判断是否没和某个矩形相交,从而跳过那些非矩形区域内的绘制操作。做了那些优化之后,我们可以通过上面介绍的Show GPU Overdraw来查看效果。

3) Custom Views and Performance(自定义视图的优化)

Android系统有提供超过70多种标准的View,例如TextView,ImageView,Button等等。在某些时候,这些标准的View无法满足我们的需要,那么就需要我们自己来实现一个View,这节会介绍如何优化自定义View的性能。

通常来说,针对自定义View,我们可能犯下面三个错误:

·Useless calls to onDraw():我们知道调用View.invalidate()会触发View的重绘,有两个原则需要遵守,第1个是仅仅在View的内容发生改变的时候才去触发invalidate方法,第2个是尽量使用ClipRect等方法来提高绘制的性能。

·Useless pixels:减少绘制时不必要的绘制元素,对于那些不可见的元素,我们需要尽量避免重绘。

·Wasted CPU cycles:对于不在屏幕上的元素,可以使用Canvas.quickReject把他们给剔除,避免浪费CPU资源。另外尽量使用GPU来进行UI的渲染,这样能够极大的提高程序的整体表现性能。

最后请时刻牢记,尽量提高View的绘制性能,这样才能保证界面的刷新帧率尽量的高。

4) Hidden Cost of Transparency(透明效果的隐藏性能消耗)

这小节会介绍如何减少透明区域对性能的影响。通常来说,对于不透明的View,显示它只需要渲染一次即可,可是如果这个View设置了alpha值,会至少需要渲染两次。原因是包含alpha的view需要事先知道混合View的下一层元素是什么,然后再结合上层的View进行Blend混色处理。

在某些情况下,一个包含alpha的View有可能会触发改View在HierarchyView上的父View都被额外重绘一次。下面我们看一个例子,下图演示的ListView中的图片与二级标题都有设置透明度。

大多数情况下,屏幕上的元素都是由后向前进行渲染的。在上面的图示中,会先渲染背景图(蓝,绿,红),然后渲染人物头像图。如果后渲染的元素有设置alpha值,那么这个元素就会和屏幕上已经渲染好的元素做blend处理。很多时候,我们会给整个View设置alpha的来达到fading的动画效果,如果我们图示中的ListView做alpha逐渐减小的处理,我们可以看到ListView上的TextView等等组件会逐渐融合到背景色上。但是在这个过程中,我们无法观察到它其实已经触发了额外的绘制任务,我们的目标是让整个View逐渐透明,可是期间ListView在不停的做Blending的操作(由于listview的适配器中getview会频繁调用,除了listview会这样,还包括grideview也会),这样会导致不少性能问题。

如何渲染才能够得到我们想要的效果呢?我们可以先按照通常的方式把View上的元素按照从后到前的方式绘制出来,但是不直接显示到屏幕上,而是使用GPU预处理之后,再又GPU渲染到屏幕上,GPU可以对界面上的原始数据直接做旋转,设置透明度等等操作。使用GPU进行渲染,虽然第一次操作相比起直接绘制到屏幕上更加耗时,可是一旦原始纹理数据生成之后,接下去的操作就比较省时省力(其实是将cpu的事落到gpu上去做,并且由于gpu的纹理机制让整体性能提升)。

如何才能够让GPU来渲染某个View呢?我们可以通过setLayerType的方法来指定View应该如何进行渲染,从SDK 16开始,我们还可以使用ViewPropertyAnimator.alpha().withLayer()来指定。如下图所示:

另外一个例子是包含阴影区域的View,这种类型的View并不会出现我们前面提到的问题,因为他们并不存在层叠的关系。

为了能够让渲染器知道这种情况,避免为这种View占用额外的GPU内存空间,我们可以做下面的设置。

通过上面的设置以后,性能可以得到显著的提升,如下图所示:

总结一下:直接和渲染相关的就是布局文件,为了达到程序渲染最优,有几个原则1.布局层数尽量少(扁平化)。2,尽量避免过度渲染。3.尽量简化布局,4,经常变化的view的布局深度尽量低(每一次变化都会涉及上层及上上层控件的变化)。这是直接和渲染机制相关的布局,渲染还提出了要求,每一个功能相对单一的模块的执行时间尽量接近16ms(这时帧率为60fps),最多为32ms,若再多就会影响用户体验了,其实16ms是一帧不落的绘制了,从16ms到32ms这段时间丢帧了,但是没影响用户体验,但是大于32ms就很影响了,卡顿慢就出现了。至于这么缩短每个模块的时间,这个就得具体模块的来定了。这里的16ms和32ms是主线程的时间,所以一般耗时较大(例如网络请求,文件操作,以及数据库操作这些典型功能就算再优化,也很难将时间压缩到16ms),这种情况就可以使用额外的线程来处理这些任务栏了,有人可能就有疑问了,既然线程可以解决问题,那我就不用优化了,直接使用线程就好了,这种说法其实是有问题的,因为线程管理还是得占用cpu时间的,如果线程数很多,cpu管理的时间就会变多,值得注意的是渲染机制的第一步解析xml布局文件(测量绘制Display List)的工作还得cpu做呢,所以可能会出现一种情况就是把耗时任务都放在新线程里了,但是依旧还是卡顿慢。所以一般是优化后距离16ms这个标准还是相差很远的情况才使用新线程。

Android app性能优化解决卡慢顿之布局优化相关推荐

  1. android 应用性能监控软件,App性能监控工具,卡顿

    (609条消息) android 应用性能监控软件,App性能监控工具_weixin_39940154的博客-CSDN博客 APP性能监测的各种工具 - ClareBaby01 - 博客园 (cnbl ...

  2. Android App 性能优化系列结语篇

    Android App 性能优化系列结语篇 原文出处:http://gold.xitu.io/post/581f4ad667f3560058a33057 关于Android App的优化, 从第一篇的 ...

  3. Android App性能优化系列

    Android App性能优化系列 关于Android App的优化,从第一篇的计划开始,到内存优化的系列文结束,不知不觉近三个月的时间,写了十五六篇相关的博文,算是对自己的知识的一个系统化,也希望能 ...

  4. Android App 性能优化总结

    Android App 性能优化系列结语篇 转发自:http://blog.lmj.wiki/2016/11/06/app-opti/app_opt_summary/#more 关于Android A ...

  5. Android APP性能优化

    转载自:https://www.cnblogs.com/qwangxiao/p/8727229.html Android APP性能优化(最新总结) 导语 安卓大军浩浩荡荡,发展已近十个年头,技术优化 ...

  6. 十大技巧优化Android App性能

    无论锤子还是茄子手机的不断冒出,Android系统的手机市场占有率目前来说还是最大的,因此基于Android开发的App数量也是很庞大的.那么,如何能开发出更高性能的Android App?相信是软件 ...

  7. Android 应用性能优化(4)---Android App性能评测分析-启动时间篇

    Android App性能评测分析-启动时间篇 1.前言 随着项目版本的迭代,App的性能问题会逐渐暴露出来,而好的用户体验与性能表现紧密相关,性能问题从应用的启动优化开始,下面会根据实际app性能测 ...

  8. Android APP性能优化(一)

    Android APP性能优化(最新总结) 安卓大军浩浩荡荡,发展已近十个年头,技术优化日异月新,如今Android 8.0 Oreo 都发布了,Android系统性能已经非常流畅了.但是,到了各大厂 ...

  9. Android App性能优化十技巧

    无论锤子还是茄子手机的不断冒出,Android系统的手机市场占有率目前来说还是最大的,因此基于Android开发的App数量也是很庞大的.那么,如何能开发出更高性能的Android App?相信是软件 ...

最新文章

  1. AI Time 7 | 人机交互的终极状态——人机共生
  2. Java IO 体系(二): inputstream与outputstream
  3. 开源杀毒引擎 ClamAV
  4. OpenKruise 如何实现 K8s 社区首个规模化镜像预热能力
  5. 解决卸载时残留目标文件夹的问题
  6. Android之jni调用java函数总结
  7. 2019-03-14-算法-进化(两个数组的交集 II)
  8. CF710F-String Set Queries【AC自动机,二进制分组】
  9. webstorm 运行android,Windows React Native环境搭建:webstorm+android studio 及解决热更新
  10. STM32学习——ROV遇到的坑
  11. Python Jupyter QtConsole
  12. java面试之简述一下 Java 垃圾回收机制?
  13. 关于163邮箱,上传附件,本地验证文件大小的问题。
  14. 业余无线电新手入门基础知识(全网最全)
  15. Badboy提示脚本错误解决方法
  16. 面试难题:本机号码一键登录原理,你知道吗?
  17. 简述网上银行的服务器端系统,网上银行系统jsp .doc
  18. 水仙花数(所有自幂数)的实现详解-C语言
  19. 基于JAVA项目任务跟踪系统计算机毕业设计源码+数据库+lw文档+系统+部署
  20. 【Linux】设备驱动简述,快速认知

热门文章

  1. (硅谷课堂项目)Java开发笔记4:前端基础知识(二)
  2. JQ彩色3D纸片折叠动画
  3. 我的-Android-面试故事---13家面试记录,附面试答案,android星座查询源码
  4. OSChina 周六乱弹 —— 三口气印度史(3.5)
  5. 不同公式等号对齐_特级老师整理:二年级数学公式、法则、儿歌、口诀
  6. 快速检索2021年EI会议论文的方法
  7. Wallpaper Engine使用视频壁纸黑屏解决方法(window10)
  8. SparkStreaming编程
  9. 飞桨 DNN波士顿房价预测
  10. 仿大众点评——美食详情