Android性能优化总结

持续更新ing

性能优化主要几个方面

  • 流畅性优化
  • 内存优化
  • CPU 优化
  • 稳定性优化
  • 安装包优化

流畅性

人眼和大脑之间的协作能感受到的最大帧率就是每秒 60 Fps 画面更新,那么要求每一帧的绘制时间就是 1000/60 = 16.67ms,所以Android系统要求每一帧尽可能在 16ms 内绘制完成

怎么看帧率?

adb shell dumpsys gfxinfo  "com.baidu.hi.debug"

// 或者
开发者模式 > GUP 呈现模式分析 > 屏幕上显示条形图 

屏幕下方的柱状图每一根代表一帧,其高度表示“渲染这一帧耗时”, 绿线代表16ms标准。每一帧的渲染过程拆分成了8个步骤:

1) Swap Buffers:表示处理任务的时间,也可以说是CPU等待GPU完成任务的时间,线条越高,表示GPU做的事情越多; 2) Command Issue:表示执行任务的时间,这部分主要是Android进行2D渲染显示列表的时间,为了将内容绘制到屏幕上,Android需要使用Open GL ES的API接口来绘制显示列表,红色线条越高表示需要绘制的视图更多;
3) Sync & Upload:表示的是准备当前界面上有待绘制的图片所耗费的时间,为了减少该段区域的执行时间,我们可以减少屏幕上的图片数量或者是缩小图片的大小;
4) Draw:表示测量和绘制视图列表所需要的时间,蓝色线条越高表示每一帧需要更新很多视图,或者View的onDraw方法中做了耗时操作;
5) Measure/Layout:表示布局的onMeasure与onLayout所花费的时间,一旦时间过长,就需要仔细检查自己的布局是不是存在严重的性能问题;
6) Animation:表示计算执行动画所需要花费的时间,包含的动画有ObjectAnimator,ViewPropertyAnimator,Transition等等。一旦这里的执行时间过长,就需要检查是不是使用了非官方的动画工具或者是检查动画执行的过程中是不是触发了读写操作等等;
7) Input Handling:表示系统处理输入事件所耗费的时间,粗略等于对事件处理方法所执行的时间。一旦执行时间过长,意味着在处理用户的输入事件的地方执行了复杂的操作;
8) Misc Time/Vsync Delay:表示在主线程执行了太多的任务,导致UI渲染跟不上vSync的信号而出现掉帧的情况;

官方详细介绍: Inspect GPU Rendering Speed and Overdraw

内存优化

为什么要内存优化?

OOM导致崩溃,频繁GC导致卡顿

优化思路

尽量少用, 尽量复用

检测内存占用?

MAT、Android Profiler、LeakCanary

内存优化点

  • 图片
    • 编码 无透明RGB565、透明的RBG8888
    • ImageView宽高 == Bitmap宽高
    • inBitmap 复用
    • 匿名共享内存(Ashmem)5.0以下
    • 优秀框架: Fresco、Glide、Picasso
  • 线程
    • 线程池 ThreadPoolExcutor
    • cpu密集型 = cpu数, IO密集 = cpu数 * 2
  • 对象池
    • 对象复用
  • 列表控件
    • RecyclerView 和 ListView 缓存对比
  • 注解
    • 减少运行时反射获取注解, 尽量用 AndroidAnnotationProcessor (apt)
  • 枚举
  • 其他优化
    • 多进程 突破heap大小瓶颈
    • SparseArray, ArrayMap 高性能集合

CPU优化

  • 优化原则
    • 能不做就不做、能少做就少做、能拖就拖、能异步就异步
    • 把一切可以放到子线程里的方法都放到子线程里
  • 检测工具 TraceView
  • APT去Runtime注解
  • 应用秒开

稳定性优化

  • 避免ANR
    • 在5秒内没有响应输入的事件(例如,按键按下,屏幕触摸)
    • BroadcastReceiver在10秒内没有执行完毕
    • 主线程在Service的各个生命周期函数时20秒内没有处理完毕
  • 避免Crash
    • 代码稳健和规范 (对可能为空的对象判空, 数组判断溢出等)
    • 监听Crash和处理 UncaughtExceptionHandler
  • 代码质量 & Code Review
  • 代码静态扫描工具
    • 常见工具有Android Lint、Findbugs、Checkstyle、PMD等等

安装包大小

  • 去除冗余的图片和代码
    • Android Lint
  • 去除不用架构so文件
    • 通常最多只留下 armeabi 和 armeabi-v7
  • 代码混淆
    • proguard-rules.pro
  • 资源混淆
  • 图片压缩
    • 采用webp、svg图片格式
    • 非透明文件采用 gif 或者 jpg
    • 图片有损压缩
    • 尽量用一张图片实现变换效果
  • APK内置大文件优先考虑从服务器下载
  • 插件化方案

参考文档