Android性能优化
Android中的性能优化基本上可以分为以下几个方面:
● 布局优化
● 网络优化
● 内存优化
● 卡顿优化
● 启动优化
布局优化
Android的布局管理器本身就是个UI组件; 所有的布局管理器都是ViewGroup的子类,而ViewGroup是View的子类,所以布局管理器可以当成普通的UI组件使用,也可以作为容器类使用,可以调用多个重载addView()向布局管理器中添加组件,并且布局管理器可以互相嵌套;当然不推荐过多的嵌套 (兼容低端机型,最好不要超过5层)
布局层级管理
让咱们一起了解一下每当系统绘制一个布局时,都会发生一些什么; 这一过程由两个步骤完成:
绘制(Measurement)
● 根布局测量自身
● 根布局要求它内部所有子组件测量自身
● 所有自布局都需要让它们内部的子组件完成这样的操作,直到遍历完视图层级中所有的View
摆放(Positioning)
● 当布局中所有的View都完成了测量,根布局则开始将它们摆放到合适的位置
● 所有子布局都需要做相同的事情,直到遍历完视图层级中所有的View
当某个View的属性发生变化(如:TextView内容变化或ImageView图像发生变化),View自身会调用View.invalidate()方法(必须从 UI 线程调用),自底向上传播该请求,直到根布局(根布局会计算出需要重绘的区域,进而对整个布局层级中需要重绘的部分进行重绘)
布局层级越复杂,UI加载的速度就越慢。因此,在编写布局的时候,尽可能地扁平化是非常重要的
FrameLayout和TableLayout有各自的特殊用途,LinearLayout 和 RelativeLayout 是可以互换的,ConstraintLayout和RelativeLayout类似
也就是说,在编写布局时,可以选择其中一种,也可以用不同的方式来编写布局
网络优化
网络优化的三个要点
多维
● 网络优化应该是多维的,一般情况下,一谈到网络优化,大部分人首先想到的就是流量消耗,但是实际上流量消耗多少只是网络优化的其中一个维度
● 只对流量消耗一个维度进行优化是不够的,甚至有的团队即便在流量优化上也没有做好,比如对于网络流量的消耗统计不够全面和精确
精准
● 在做网络流量统计时,我们要做精准度量,如果只是获取了具体消耗了多少的值,对于我们定位和解决问题是没有太大的帮助,因为这个值只能表明用户用了多少流量
● 如果线上用户反馈 App 消耗流量较多,但是我们不知道这个用户总共使用了 App 多长时间的话,那就不好定位问题所在,如果用户使用 App 的时间比较长,那消耗流量多一些很可能是正常的
● 又比如用户反馈 App 在后台消耗流量比较多,但是我们只统计了整体的值,那就无法断定 App 在后台运行时到底消耗了多少流量
监控
● 针对网络优化,我们应该建设全面且完善的网络监控体系,不能只监控一个指标,假如只监控网络请求成功率,那我们就只能知道用户大概的网络使用情况,这种粗粒度的监控没办法帮助我们找出并解决问题的根源
● 比如线上用户使用了某个功能使用了 1000 次,然后出现了 1 次异常,而且用户点击重试后就恢复正常了
● 这样单从数据上来看的话,网络请求的成功率还是比较高的,但是只通过成功率一个值是无法知道这一次异常出现的原因,也就无法避免后续出现这类异常
网络优化的两个维度
流量维度
● 流量维度也就是 App 在一段时间内流量消耗的精准度量
● 流量消耗大不仅对用户有影响,对公司的运营成本也有影响,比如带宽、服务器数量、CDN 等方面的开支,而且网络请求密集对手机耗电量也有一定的影响
● 在流量维度上,我们要做到区分类型、监控异常、上报日志
区分类型
● 我们不仅要知道用户在某个时间段内的具体流量消耗,还要知道用户在不同网络类型(流量、WiFi)下的流量消耗、区分 App 在前台和在后台时的流量消耗
● 只有积累了不同维度的数据,才能快速断定和解决问题
监控异常
对于流量统计,我们不仅要知道用户的流量消耗均值,还要知道线上用户消耗流量的异常率。
这里的异常分为三种:
● 流量消耗过多
● 请求次数过多
● 下载文件过大
这三个都是我们要注意的异常
上报日志
● 最理想的情况,就是我们对所有的网络请求,在本地都有一个完整的监控,每一个请求的 Request 和 Response 相关的所有信息都全部记录下来
● 服务端可以下发指令控制客户端上传这些数据,客户端也可以在相关数据超过阈值后主动上报
质量维度
网络请求的质量也非常关键,它直接对应了用户的真实体验,如果网络请求速度慢或请求成功率比较低,都会导致不好的用户体验
对于网络请求质量的监控,可以从下面几个维度进行区分,以便后续能快速定位和解决问题
● 请求时长
● 请求成功率
● 失败率
● Top 失败接口
网络优化的两个误区
只关注流量
● 只关注流量消耗,忽视了其他维度
忽略个体数据
● 还有就是做网络监控时只关注均值和整体的数据,忽略了个体的数据
● 比如前面提到的请求成功率的例子,从整体上来看成功率非常高,但是这种数据无法帮助我们改善单次请求
● 做内存优化的目的是降低OOM
率、减少卡顿、增加应用存活时间
内存优化
降低OOM
率
● 做内存优化的一个常见原因是为了降低OOM
率 申请内存过多而没有及时释放,常常就会导致OOM
引起OOM
的原因有多种,在后面我们再细谈
减少卡顿
● Android
中造成界面卡顿的原因有很多种,其中一种就是由内存问题引起的. 内存问题之所以会影响到界面流畅度,是因为垃圾回收. 在GC
时,所有线程都要停止,包括主线程.当GC
和绘制界面的操作同时触发时,绘制的执行就会被搁置,导致掉帧,也就是界面卡顿
增加应用存活时间
● Android
会按照特定的机制清理进程,清理进程时优先会考虑清理后台进程,如果某个应用在后台运行并且占用的内存更多,就会被优先清理掉 我们通常希望App
能尽量存活的久一点,所以内存不再使用时应该尽快释放
导致卡顿的因素
● 硬件因素:CPU、RAM、ROM、HeapSize、SDK Version
● 软件因素:UI渲染相关、UI线程操作相关
卡顿优化
如何定义发生了卡顿现象:
● 如果App的FPS平均值小于30,最小值小于24,即表明应用发生了卡顿
● 线下很难复现,与发生场景强相关(所以需要我们去做卡顿监控,收集现场信息)
CPU相关知识
● 现在最新的主流机型都使用了多级能效的CPU架构(即多核分层架构)
● 从 CPU 到 GPU 再到 AI 芯片NPU,随着手机 CPU 整体性能的飞跃, 我们可以充分利用移动端的计算能力来降低高昂的服务器成本
● 评价一个 CPU 的性能,需要看主频、核心数、缓存等参数,具体表现出来的是计算能力和指令执行能力,也就是每秒执行的浮点计算数和每秒执行的指令数
● 造成卡顿的原因很多(涉及到代码、内存、绘制、IO、CPU等),最终都反映到 CPU 时间上; CPU时间 可以分为用户时间和系统时间:
● 用户时间:执行用户态应用程序代码所消耗的时间
● 系统时间:执行内核态系统调用所消耗的时间,包括 I/|O、锁、中断以及其他系统调用的时间
CPU相关的三类问题
CPU资源冗余使用:
● 算法效率低
● 没使用缓存
● 计算时使用的基本类型不对(如int足够却用long,运算压力多出4倍)
CPU资源争抢:
● 抢主线程的CPU资源
● 抢音视频的CPU资源
● 编解码本身会消耗大量的CPU资源,并且其对于解码的速度是有硬性要求的,如果达不到就可能产生播放流畅度的问题
采取两种方式去优化:
● 尽量排除非核心业务的消耗
● 优化自身的性能消耗,把CPU负载转化为GPU负载,如使用renderscript来处理视频中的影像信息
大家平等,互相抢(三个和尚没水喝)
CPU资源利用率低:
● 有磁盘和网络I/O,还有锁操作、sleep等等, 对于锁的优化,通常是尽可能地缩减锁的范围
启动优化
网上流行一种说法,就是8秒定律,意思是说,如果用户在打开一个页面,在8秒的时间内还没有打开,那么用户大概的会放弃掉,意味着一个用户的流失。从这里就可以看出,启动优化的重要性了
启动的分类
冷启动
先来看看冷启动的流程图:
从图中可以看出,APP启动的过程是:ActivityManagerProxy 通过IPC来调用AMS(ActivityManagerService),AMS通过IPC启动一个APP进程,ApplicationThread通过反射来创建Application并且绑定,最后通过ActivityThread来控制activity的生命周期,在相关页面的生命周期中通过ViewRootImpl来对view的实现;从而完成应用的启动
热启动
热启动的速度是最快的,它就是进程从后台切换到前台的一个过程。
温启动
温启动只会重新走一遍页面的生命周期,但是对于进程,application不会重新在创建。
优化方向
上面介绍了启动的几种方式可以看出,我们针对启动优化,基本只是优化冷启动就可以了。但是从冷启动的启动流程中很多都是系统做的,我们没有办法操控。我们能做的,就是application的生命周期和activity的生命周期这部分,启动优化往往就是从这两块入手。
优化总结
性能优化是我们进阶的必经之路
所以,我们必须要会,至于“会”到什么程度,就要看个人理解了
其实,上面介绍的只是性能问题的冰山一角,真正的优化,我们是在项目中总结出来的;但,我们不能一味的追求优化,就例如我,现在只是在进行优化的总结,而对于真正的实行,并没有开始,因为,优化是有风险的,一个不小心,整个项目都可能炸了
所以这就需要你的经验,以及各种总结,在改进行优化的地方先进行优化,看看效果如何,例如,UI的优化以及代码的优化
可以先拿一些网上的开源项目进行优化等等
也可以点击 “此处” 获取更多 Android学习笔记
网友评论