三. Android 布局优化
1. Android绘制原理及工具选择
1.1 绘制分析
CPU:负责计算显示内容。视图的创建,布局计算,图片解码,文本绘制。
GPU:负责栅格化操作(UI元素绘制到屏幕上),Button拆分成像素。换算成纹理。
16ms 发出VSync信号出发 UI 渲染。
大多数的Android设备屏幕刷新频率:60HZ
1.2 优化工具
Systrace
关注Frames
正常:绿色圆点,丢帧:黄色或红***r> Alerts栏。自动分析异常性能分析的一些条目
Layout Inspector
查看视图层次结构
Choreographer(API16以后)
获取FPS,线上使用,具备实时性
Choreographer.getInstance().postFrameCallback
2. Android布局加载原理
深入布局加载源码:
setContentView -> LayoutInflater -> inflate -> getLayout -> createViewFromTag -> Factory -> createView -> 反射
性能瓶颈
布局文件解析:IO过程。布局特别大,文件也就特别大,io也就会卡顿。
创建View对象:反射。反射使用过多(标签过多)导致反射很慢。
LayoutInflater.Factory
LayoutInflater 创建View的一个Hook
定制创建View的过程:全局替换自定义TextView等
LayoutInflater当中的 Factory与Factory2
Factory2继承于Factory
多了一个参数:parent
3. 优雅获取界面布局耗时
3.1 常规方式
获取每个界面的加载耗时。
实现:复写setContentView、手动埋点。不够优雅,代码有侵入性。
3.2 AOP/ArtHook
找到切面点。切Activity的setContentView。
@Around("execution(* android.app.Activity.setContentView(..))")
call表示切在方法调用的部分。execution表示切在方法的里面
获取任一控件的加载耗时 ,在内部和执行方法处和启动时间计算方式一致。
低侵入性。
LayoutInflater.Factory
3.3 异步Inflate实战
布局文件读取过程慢,IO过程
创建view过程慢,反射过程创建,比new慢3倍。
根本性解决。不使用反射/IO
侧面缓解。
AsyncLayoutInflater(异步Inflater)
- WorkThread加载布局
- 回调主线程
- 节约主线程时间
导包:
com.android.support:asynclayoutinflater
4. 布局加载优化实战
AsyncLayoutInflater只是缓解。
Java代码写布局,它的缺点是不便于开发、可维护性差。
X2C框架(通过APT编译器翻译XML为Java代码)
开发人员写XML,加载Java代码。
annotationProcessor 'com.zhangyue.we:x2c-apt:1.1.2'
implementation 'com.zhangyue.we:x2c-lib:1.0.6'
用到的页面使用:@Xml(layouts = "activity_main")
问题:部分属性Java不支持、失去了系统的兼容(AppCompat)
5. 视图绘制优化实战
优化布局层级及复杂度
测量:确定大小
布局:确定位置
绘制:绘制视图
性能瓶颈:每个阶段耗时。自顶向下遍历。触发多次。
准则:减少View树层级。
宽而浅,避免窄而深
(布局层级 从上往下叫宽度,所有元素尽可能在一个ViewGroup当中)
(布局深度尽可能更浅)
1)ConstrainLayout:实现几乎完全扁平化布局。构建复杂布局性能更高。具有RelativeLayout和LinearLayout的特性
2)不嵌套使用RelativeLayout
3)不在嵌套LinearLayout中使用weight
4)merge标签:减少一个层级,只能用于根View
过度绘制
一个像素最好只会被控制一次。
5)调试GPU过度绘制(开发者模式中打开)
蓝色可接受
避免过度绘制方法
6)去掉多余背景色,减少复杂shape使用
7)避免层级叠加
8)自定义View使用 clipRect 屏蔽被遮盖View绘制
9)ViewStub:高效占位符、延迟初始化
10)onDraw中避免:创建大对象、耗时操作。
11)TextView优化
6. 总结
用到了哪些工具?
结构化思维。使用了很多工具,有不同的使用场景。
1)Choreographer 可以带到线上,得到帧率。
2)每个布局耗时 AOP、HOOK
3)线下开发环节、Systrace、Layout Inspector
4)布局为什么会导致卡顿,你又是如何优化的?
5)IO、反射、遍历、重绘
6)异步Inflate、X2C、减少层级、重绘
7)AOP、监控
8)做完布局优化后有哪些成果产出?
9)体系化监控手段:线下 + 线上
指标:FPS、加载时间、布局层级
核心路径保障