安卓系列之性能知识点
GC
Garbage Collector,垃圾回收机制。
内存抖动
Memory Churn,短时间内有大量的对象被创建或者被回收的现象。
优化方案
- 不在循环内创建新对象。
- 不要在自定义 View 的 onDraw()方法内频繁创建对象。
- 当需要大量使用 Resource 的时候,缓存在数组中实现复用。
- 对于能够复用的对象,可以利用缓存机制。
内存泄漏
程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
LeakCanary
内存泄漏检测工具 APP
如何检测
通过一个弱引用(WeakReference)和一个引用队列(ReferenceQueue)检测对象是否被 GC 回收成功,判断条件是弱引用所引用的对象被 GC 回收后,虚拟机会把这个弱引用加入与之关联的引用队列中,然后查询这个对象是否被 GC 回收成功。
流程
-
对象添加到监控列表
-
GC 扫描回收
-
从引用队列中获取引用
-
判断是否回收成功
- 是,从监控列表中转移到保留列表中
- 否,从监控列表中移除
AMS
ActivityManagerService,管理 Activity 的创建和销毁。
场景
- 单例
单例引用上下文导致内存泄漏,可以使用全局上下文替代。 - 静态变量
静态对象使用上下文导致内存泄漏,可以使用全局上下文替代。 - 非静态内部类
例如:在 Activity 创建 Handler 匿名内部类。 - 没有取消的注册或者回调
例如:广播和 eventbus。 - Timer 和 TimerTask
定时器 - 资源未释放
例如:IO 流,File 流等。 - 属性动画
在 Activity 或者 Fragment 销毁的时候暂停并销毁。 - Webview
需要在 Activity 的 onDestory()方法中从父容器移除且销毁 Webview 来解决。
OOM
OOM(内存溢出) 可以通过性能工具进行观察定位问题。
归属
OOM 属于 Error 错误,非 Exception 错误。
案例
- 大图加载
- 内存泄漏
图片压缩
- 质量压缩
改变位深和透明度进行压缩。使用 Bitmap.compress()。 - 尺寸压缩
两次 decode,使用 Bitmap.option()。 - Native 压缩
使用 libjpeg.so 库(哈夫曼算法)。
UI 优化
优化方案
- 优先使用 LinearLayout 和 FrameLayout,减少使用 RelativeLayout。
- 减少重叠颜色的填充。
- 使用 include 和 merge 增加复用。
- ViewStub 按需加载,更加轻便。
- 复杂界面优先使用 ConstraintLayout。
- Activity 内的动画效果在 onDestory()方法中 cancel。
- 不要在自定义 View 的 onDraw()方法内做耗时操作。
检测工具
- 开发者-> 调试 GPU 过度绘制 -> 红色区域均是绘制过度
- 开发者-> 监控 -> GPU 呈现模式-> 在屏幕上显示为条形图 -> 超过红色警戒线的即是超过 16ms 绘制时长
启动速度优化
启动方式
- 冷启动 指应用程序从头开始。
- 暖启动 包含了冷启动时发生的一些操作,减少了对象初始化、布局加载等工作,启动时间更短。
- 热启动 把 Activity 带到前台。
时间对比
冷启动 > 暖启动 > 热启动
优化方案
- 去除开屏页,使用 theme 加载开屏效果。
- 优化减少网络请求完才可以进入主页。
- 避免在 Application 中做耗时操作。
包体积优化
- lint 工具删除不需要的资源文件。
- 打包开启资源压缩和自动删除无用资源。
shrinkResources true
minifyEnabled true
- 少用切图,使用 shape 实现效果,例如按钮背景。
- 同一张图,可以使用动画去实现不同状态,例如展开和收起的三角按钮。
- 利用 TinyPNG 等第三方压缩网站对图片进行压缩处理。
- 混淆打包。
- 插件化。
耗电优化
- JobScheduler 任务调度,在系统某些特定情况下对数据进行处理,例如电量变化的时候进行数据上传等。
其他优化
- 耗时操作不要在主线程中。
- 使用线程的时候需要配合线程池。
- 使用 Analyze->Inspect Code 进行代码优化。