-
优化目的
- 尽量减少主线程操作
- 尽量减少GC
-
优化流程
- 首先通过SM(帧率)对App的流畅度进行测试评估(引入APM情况下)。
- 然后从最简单的App UI层入手,优化App的UI来提升流畅度。
- 接着通过lint静态扫描发现一部分代码中存在的性能问题,然后进行优化。
- 最后再进一步深入的分析和解决App逻辑层和IO层存在的问题
1. 布局优化
-
减少布局复杂度
-
尽量减少不必要的嵌套
使用include和merge增加复用,减少层级
使用ViewStub按需加载
3层以上的复杂页面选择使用ConstraintLayout -
在相同层级结构相同并且界面效果相同时,选择性能高的ViewGroup
FrameLayout>LinearLayout>RelativeLayout,同时也可以自定义ViewGroup来减少计算量。
-
-
避免过渡绘制(开启GPU过度渲染)
- 去掉不必要的背景
- 使用Space标签
- 不必要的alpha值设置可以解决同一视图被多次绘制的问题
2. 绘制优化
-
onDraw方法中不要做耗时的任务
onDraw方法中不要做耗时的任务,也不做过多的循环操作,特别是嵌套循环,虽然每次循环耗时很小,但是大量的循环势必霸占CPU的时间片,从而造成View的绘制过程不流畅。 -
onDraw中不要创建新的局部对象
onDraw()中不要创建新的局部对象,因为onDraw()方法一般都会频繁大量调用,就意味着会产生大量的临时对象,不仅占用过的内存,而且会导致系统更加频繁的GC,大大降低程序的执行速度和效率。 -
避免不必要的绘制
自定义控件时canvas.clipRect可以解决只刷新固定区域的问题,可参考DrawerLayout
3. 内存优化
-
避免内存泄露
- 集合类内存泄漏(持有空对象引用)
- 单例/静态变量造成的内存泄漏
- 匿名内部类/非静态内部类
- 资源未关闭造成的内存泄漏
-
避免内存抖动(Memory Minotor)
- 避免在for循环中new大对象或数组
- 避免在onDraw()方法中new大对象或数组
-
避免OOM
- 避免内存泄露
- Bitmap尽量使用Glide加载
- Bitmap优化(质量压缩、尺寸压缩)
-
避免使用枚举
- 使用常量,使用@IntDef
Enum 到底占多少内存
正确使用枚举
- 使用常量,使用@IntDef
4. 启动速度优化(trace)
-
冷启动优化
- 利用提前展示出来的Window,快速展示出来一个界面,给用户快速反馈的体验;
- 避免在启动时做密集沉重的初始化(Heavy app initialization)
- 避免I/O操作、反序列化、网络操作、布局嵌套等
-
Activity启动优化
5. 代码优化
选择正确的算法和数据结构应始终是我们的首要任务,以提高代码效率。
- 避免创建不必要的对象
- 方法特定场景下使用静态方法
- 对常量使用static final
- 使用增强的for循环语法(RandomAccess例外)
- 避免使用浮点数
- 避免使用反射
...
6. 包大小优化
- 代码混淆
- 资源优化
- 方法数优化
- 插件化
7. 耗电优化
- 使用JobScheduler调度任务
- 使用懒惰法则
网友评论