AndroidAPP性能优化的四个⽅⾯最全总结
说到Android系统⼿机,⼤部分⼈的印象是⽤了⼀段时间就变得有点卡顿,有些程序在运⾏期间莫名其妙的出现崩溃,打开系统⽂件夹⼀看,发现多了很多⽂件,然后⽤⼿机管家 APP 不断地进⾏清理优化 ,才感觉运⾏速度稍微提⾼了点,就算⼿机在各种性能跑分软件⾯前分数遥遥领先,还是感觉⽆论有多⼤的内存空间都远远不够⽤。相信每个使⽤Android系统的⽤户都有过以上类似经历,确实,Android系统在流畅性⽅⾯不如iOS系统,为何呢,明明在看⼿机硬件配置上时,Android设备都不会输于iOS设备,甚⾄都强于它,关键是在于软件上。造成这种现象的原因是多⽅⾯的,简单罗列⼏点如下:
性能优化
今天想说的重点是Android APP性能优化,也就是在开发应⽤程序时应该注意的点有哪些,如何更好地提⾼⽤户体验。⼀个好的应⽤,除了要有吸引⼈的功能和交互之外,在性能上也应该有⾼的要求,即时应⽤⾮常具有特⾊,在产品前期可能吸引了部分⽤户,但是⽤户体验不好的话,也会给产品带来不好的⼝碑。那么⼀个好的应⽤应该如何定义呢?主要有以下三⽅⾯:
众所周知,Android系统作为以移动设备为主的操作系统,硬件配置是有⼀定的限制的,虽然配置现在越来越⾼级,但仍然⽆法与PC相⽐,在CPU和内存上使⽤不合理或者耗费资源多时,就会碰到内存不⾜导致的稳定性问题、CPU 消耗太多导致的卡顿问题等。
⾯对问题时,⼤家想到的都是联系⽤户,然后查看⽇志,但殊不知有关性能类问题的反馈,原因也⾮常难,⽇志⼤多⽤处不⼤,为何呢?因为性能问题⼤部分是⾮必现的问题,问题定位很难复现,⽽⼜没有关键的⽇志,当然就⽆法到原因了。这些问题⾮常影响⽤户体验和功能使⽤,所以了解⼀些性能优化的⼀些解决⽅案就显得很重要了,并在实际的项⽬中优化我们的应⽤,进⽽提⾼⽤户体验。
四个⽅⾯
可以把⽤户体验的性能问题主要总结为4个类别:
性能问题的主要原因是什么,原因有相同的,也有不同的,但归根到底,不外乎内存使⽤、代码效率、合适的策略逻辑、代码质量、安装包体积这⼀类问题,整理归类如下:
从图中可以看到,打造⼀个⾼质量的应⽤应该以4个⽅向为⽬标:快、稳、省、⼩。
要想达到这4个⽬标,具体实现是在右边框⾥的问题:卡顿、内存使⽤不合理、代码质量差、代码逻辑乱、安装包过⼤,这些问题也是在开发过程中碰到最多的问题,在实现业务需求同时,也需要考虑到这点,多花时间去思考,如何避免功能完成后再来做优化,不然的话等功能实现后带来的维护成本会增加。
卡顿优化
Android 应⽤启动慢,使⽤时经常卡顿,是⾮常影响⽤户体验的,应该尽量避免出现。卡顿的场景有很多,按场景可以分为4类:UI 绘制、应⽤启动、页⾯跳转、事件响应,如图:
这4种卡顿场景的根本原因可以分为两⼤类:
引起卡顿的原因很多,但不管怎么样的原因和场景,最终都是通过设备屏幕上显⽰来达到⽤户,归根到底就是显⽰有问题,所以,要解决卡顿,就要先了解Android系统的显⽰原理。
And r oi d系统显⽰原理
Android显⽰过程可以简单概括为:Android应⽤程序把经过测量、布局、绘制后的Surface缓存数据,通过SurfaceFlinger把数据渲染到显⽰屏幕上, 通过Android的刷新机制来刷新数据。也就是说应⽤层负责绘制,系统层负责渲染,通过进程间通信把应⽤层需要绘制的数据传递到系统层服务,系统层服务通过刷新机制把数据更新到屏幕上。
我们都知道在Android的每个View绘制中有三个核⼼步骤:Measure、Layout、Draw。具体实现是从 ViewRootImp类的performTraversals() ⽅法开始执⾏,Measure和Layout都是通过递归来获取View的⼤⼩和位置,并且以深度作为优先级,可以看出层级越深、元素越多、耗时也就越长。
真正把需要显⽰的数据渲染到屏幕上,是通过系统级进程中的SurfaceFlinger服务来实现的,那么这个SurfaceFlinger服务主要做了哪些⼯作呢?如下:
既然是两个不同的进程,那么肯定是需要⼀个跨进程的通信机制来实现数据传递,在Android显⽰系统中,使⽤了Android的匿名共享内存:SharedClient,每⼀个应⽤和SurfaceFlinger之间都会创建⼀个SharedClient ,然后在每个SharedClient中,最多可以创建31个 SharedBufferStack,每个Surface都对应⼀个SharedBufferStack,也就是⼀个Window。
⼀个SharedClient对应⼀个Android应⽤程序,⽽⼀个Android应⽤程序可能包含多个窗⼝,即Surface。也就是说SharedClient包含的是SharedBufferStack的集合,其中在显⽰刷新机制中⽤到了双
缓冲和三重缓冲技术。最后总结起来显⽰整体流程分为三个模块:应⽤层绘制到缓存区,SurfaceFlinger把缓存区数据渲染到屏幕,由于是不同的进程,所以使⽤Android的匿名共享内存SharedClient缓存需要显⽰的数据来达到⽬的。
除此之外,我们还需要⼀个名词:FPS。FPS表⽰每秒传递的帧数。在理想情况下,60FPS就感觉不到卡,这意味着每个绘制时长应该在16ms以内。但是 Android系统很有可能⽆法及时完成那些复杂的页⾯渲染操作。Android系统每隔16ms发出VSYNC信号,触发对UI 进⾏渲染,如果每次渲染都成功,这样就能够达到流畅的画⾯所需的60FPS。如果某个操作花费的时间是24ms ,系统在得到VSYNC信号时就⽆法正常进⾏正常渲染,这样就发⽣了丢帧现象。那么⽤户在32ms内看到的会是同⼀帧画⾯,这种现象在执⾏动画或滑动列表⽐较常见,还有可能是你的Layout太过复杂,层叠太多的绘制单元,⽆法在16ms完成渲染,最终引起刷新不及时。
卡顿根本原因
根据Android系统显⽰原理可以看到,影响绘制的根本原因有以下两个⽅⾯:
android最新版绘制耗时太长,有⼀些⼯具可以帮助我们定位问题。主线程太忙则需要注意了,主线程关键职责是处
理⽤户交互,在屏幕上绘制像素,并进⾏加载显⽰相关的数据,所以特别需要避免任何主线程的事情,这样应⽤程序才能保持对⽤户操作的即时响应。总结起来,主线程主要做以下⼏个⽅⾯⼯作:
除此之外,应该尽量避免将其他处理放在主线程中,特别复杂的数据计算和⽹络请求等。
性能分析⼯具
性能问题并不容易复现,也不好定位,但是真的碰到问题还是需要去解决的,那么分析问题和确认问题是否解决,就需要借助相应的的调试⼯具,⽐如查看Layout层次的Hierarchy View、Android系统上带的GPU Profile⼯具和静态代码检查⼯具Lint等,这些⼯具对性能优化起到⾮常重要的作⽤,所以要
熟悉,知道在什么场景⽤什么⼯具来分析。
1,Profile GPU Rendering
在⼿机开发者模式下,有⼀个卡顿检测⼯具叫做:Profile GPU Rendering,如图:
它的功能特点如下:
2,TraceView
TraceView是Android SDK⾃带的⼯具,⽤来分析函数调⽤过程,可以对Android的应⽤程序以及Framework层的代码进⾏性能分析。它是⼀个图形化的⼯具,最终会产⽣⼀个图表,⽤于对性能分析进⾏说明,可以分析到每⼀个⽅法的执⾏时间,其中可以统计出该⽅法调⽤次数和递归次数,实际时长等参数维度,使⽤⾮常直观,分析性能⾮常⽅便。
3,Systrace UI 性能分析
Systrace是Android 4.1及以上版本提供的性能数据采样和分析⼯具,它是通过系统的⾓度来返回⼀些信息。它可以帮助开发者收集Android关键⼦系统,如Surfaceflinger、WindowManagerService等Framework部分关键模块、服务、View系统等运⾏信息,从⽽帮助开发者更直观地分析系统瓶颈,改进性能。Systrace的功能包括跟踪系统的I/O操作、内核⼯作队列、CPU负载等,在UI显⽰性能分析上提供很好的数据,特别是在动画播放不流畅、渲染卡等问题上。
优化建议
1,布局优化
布局是否合理主要影响的是页⾯测量时间的多少,我们知道⼀个页⾯的显⽰测量和绘制过程都是通过
递归来完成的,多叉树遍历的时间与树的⾼度h有关,其时间复杂度O(h),如果层级太深,每增加⼀层则会增加更多的页⾯显⽰时间,所以布局的合理性就显得很重要。
那布局优化有哪些⽅法呢,主要通过减少层级、减少测量和绘制时间、提⾼复⽤性三个⽅⾯⼊⼿。总结如下:
2,避免过度绘制
过度绘制是指在屏幕上的某个像素在同⼀帧的时间内被绘制了多次。在多层次重叠的UI结构中,如果不可见的UI也在做绘制的操作,就会导致某些像素区域被绘制了多次,从⽽浪费了多余的CPU以及GPU源。
如何避免过度绘制呢,如下:
3,启动优化
通过对启动速度的监控,发现影响启动速度的问题所在,优化启动逻辑,提⾼应⽤的启动速度。启动主要完成三件事:UI布局、绘制和数据准备。因此启动速度优化就是需要优化这三个过程:
4,合理的刷新机制
在应⽤开发过程中,因为数据的变化,需要刷新页⾯来展⽰新的数据,但频繁刷新会增加资源开销,并且可能导致卡顿发⽣,因此,需要⼀个合理的刷新机制来提⾼整体的UI流畅度。合理的刷新需要注意以下⼏点:
5,其他
在实现动画效果时,需要根据不同场景选择合适的动画框架来实现。有些情况下,可以⽤硬件加速⽅式来提供流畅度。
内存优化
在Android系统中有个垃圾内存回收机制,在虚拟机层⾃动分配和释放内存,因此不需要在代码中分配和释放某⼀块内存,从应⽤层⾯上不容易出现内存泄漏和内存溢出等问题,但是需要内存管理。Android系统在内存管理上有⼀个Generational Heap Memory模型,内存回收的⼤部分压⼒不需要应⽤层关⼼,Generational Heap Memory有⾃⼰⼀套管理机制,当内存达到⼀个阈值时,系统会根据不同的规则⾃动释放系统认为可以释放的内存,也正是因为Android程序把内存控制的权⼒交给了Generational Heap Memory,⼀旦出现内存泄漏和溢出⽅⾯的问题,排查错误将会成为⼀项异常艰难的⼯作。除此之外,部分Android应⽤开发⼈员在开发过程中并没有特别关注内存的合理使⽤,也没有在内存⽅⾯做太多的优化,当应⽤程序同时运⾏越来越多的任务,加上越来越复杂的业务需求时,完全依赖Android 的内存管理机制就会导致⼀系列性能问题逐渐呈现,对应⽤的稳定性和性能带来不可忽视的影响,因此,解决内存问题和合理优化内存是⾮常有必要的。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论