Android性能优化总结

446 阅读4分钟

性能优化

Android性能优化-系列-头条祁同伟
Android性能优化典范-胡凯

image

  • 流畅度
  • 内存优化
  • 电量、网络优化
  • 安装包优化

一、流畅度优化

影响因素

  • 界面过渡绘制
  • 启动初始化卡顿
  • 大数据在UI线程处理
  • 动画消耗CPU资源
  • 内存泄漏引发GC卡顿
  • ANR

1、绘制相关

Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染。如果每次渲染都成功,这样就能够达到流畅的画面所需要的60fps,为了能够实现60fps,这意味着程序的大多数操作都必须在16ms内完成。

1.1、CPU、GPU

先经过CPU的计算加载到内存中,然后传递给GPU进行渲染

CPU

CPU:中央处理器(英文Central Processing Unit)是一台计算机的运算核心和控制核心。

  • 顺序执行
  • 进行计算、移位、存储等简单工作
GPU

GPU:英文全称Graphic Processing Unit,“图形处理器”。一个专门的图形核心处理器。
GPU是显示卡的“大脑”,决定了该显卡的档次和大部分性能,同时也是2D显示卡和3D显示卡的区别依据。2D显示芯片在处理3D图像和特效时主要依赖CPU的处理能力,称为“软加速”。3D显示芯片是将三维图像和特效处理功能集中在显示芯片内,也即所谓的“硬件加速”功能。

  • 并行执行
  • 图像、密码破译、大数据处理、金融分析
1.2、帧率、16ms

60fps作为App性能的衡量标准(人眼无法感知超过60fps的画面更新)
为了能够使得App流畅,我们需要在每一帧16ms以内处理完所有的CPU与GPU计算,绘制,渲染等等操作

  • 1000ms/60fps(帧率) = 16ms
1.3、Android绘制检测工具
  • Tracer for OpenGL查看过渡绘制
  • Tools --> Layout inspector
  • 开发者选项 --> GPU渲染分析
    • 颜色区分过渡绘制的次数
    • adb shell setprop debug.hwui.overdraw show
    • adb shell setprop debug.hwui.overdraw false
      image
1.4、过度绘制 OverDraw

image

屏幕上的某个像素在同一帧的时间内被绘制了多次。
在多层次的UI结构里面,如果不可见的UI也在做绘制的操作,这就会导致某些像素区域被绘制了多次。这就浪费大量的CPU以及GPU资源。

Android性能优化之渲染篇
Android 过度绘制优化
使用clipRect()优化OverDraw

场景
避免多次绘制相同内容
  • RecyclerView更新内容
    • DiffUtil只更新有变化的内容
  • 多重背景设置:Act、父、子等都设置各自背景
    • 移除主题window背景 @null
    • 移除不必要Background背景设置,如ViewGroup、View都各自设置的相同背景
    • 按需显示占位图
避免绘制隐藏内容
  • 自定义View:被覆盖部分本无需绘制
    • ClipRect & QuickReject
    • 使用clipRect()优化OverDraw裁剪矩形内需要绘制的界面
    • canvas.quickreject()来判断是否没和某个矩形相交,从而跳过那些非矩形区域内的绘制操作
优化布局代码,减少View视图层级
  • 减少视图的深度,来减少视图树的遍历过程
  • ConstraintLayout等减少层级
  • 使用ViewStub:动态布局内容,不显示时不绘制
  • 慎用Alpha:先绘制透明度界面,再绘制颜色,绘制两次
  • 标签:减少一个层级

2、App启动优化

应用启动时间-Dev
Android App 启动优化全记录
!!!!!面试官:今日头条启动很快,你觉得可能是做了哪些优化?
都9102年了,Android 冷启动优化除了老三样还有哪些新招?

启动流程

冷启动、温启动、热启动

冷启动流程
  1. 加载并启动应用
  2. 在启动后立即显示应用的空白启动窗口
  3. 创建应用进程

系统一创建应用进程,应用进程就负责后续阶段:

  1. 创建应用对象
  2. 启动主线程
  3. 创建主 Activity
  4. 扩充视图
  5. 布局屏幕
  6. 执行初始绘制
    image
优化方向
视觉优化
  • 默认启动Theme(windowBackground) --> 切换回正常Theme(setContent之前)
  • ViewStub 替代在启动过程中不需要显示的 UI 控件(需要时再加载替换)
  • 闪屏广告页面: 闪屏时间(固定) = App启动时间 + 闪屏时间(动态)
密集型应用初始化(Application/Activity)
  • 立即主线程初始化
  • 延迟主线程初始化
  • 子线程初始化
MultipDex优化
通过redex重排列class文件
耗时分析和初始化顺序
启动耗时统计
  • logcat: Displayed
  • adb [-d|-e|-s ] shell am start -S -W
  • reportFullyDrawn()
启动耗时工具分析

使用 CPU Profiler 检查 CPU 活动
Systrace + 函数插桩
Systrace系列
使用 Traceview 检查跟踪日志--已废弃

3、大数据在UI线程处理

数据处理量太大,一般分为三种情况

  • 一是数据在UI 线程处理
  • 二是数据处理占用 CPU 高,导致主线程拿不到时间片
场景优化
  • 使用StringBuilder、SparseMap
  • 使用缓存
  • 放到子线程执行

4、动画消耗CPU资源

5、内存泄漏引发GC卡顿

6、ANR