android 渲染的几个关键词
surfaceflinger -> 刷新率
编舞者 -> 制图速度 choreographer /ˌkɔːriˈɑːɡrəfər/
vsync 垂直同步信号.
一秒60帧, 16.66ms通过vsync信号触发一次刷新.
卡顿的主观因素
- main looper里的event事件的处理有没有耗时问题.
- 测量, 布局, draw当中的代码运行速度慢. 因此不要在这三个方法中进行大量运算.
- 布局层叠深度不要过深. 过深的话就会有很多view需要执行测量, 布局, draw当中的代码.
卡顿的客观因素
- JVM GC STW (stop the world)会让所有线程, 包括UI线程都会暂停.
- binder通信, 和其他进程的调用被卡住了.
使用systrace定位问题
事故类型是什么.
1.1 UI绘制导致的问题 绿色偏多导致超时
1.2 事件处理导致的问题 绿色偏多导致超时
1.3 层级过多导致的绘制超时
1.4 GC导致的超时 UI线程 紫色频繁
1.5 IO导致的超时 UI线程 橙色频繁
1.6 binder通信导致的超时 UI线程 灰色频繁
systrace是定位不到代码具体的位置的, 它是用来定位事故类型的.
systrace的使用. 启动后, 手动操作, 然后结束.
systrace会把这期间的帧率变化, 线程状态给记录下来.
在frame这栏里, 间歇性的稍微红几帧的地方不用去看, 可能当时jvm在gc, 这种情况是可以接受的, 偶尔性的掉6,7帧不影响用户体验.
要看frame这栏里, 那种连续红和黄的位置, 这才是卡顿发生的时间段.
之后看UIThread这栏 中 choreographer#doFrame 这行的颜色, 不同颜色对应着不同的事故类型.
卡顿代码的定位
可以使用开源的BlockCanary定位, 实现思路是通过ActivityThread里有个logging对象来记录msg的处理开始和结束时间. 并且ActivityThread对外提供了setLogging()的方法. 因此可以在外部创建出一个自己的logging对象set进去. 时间超过阈值的时候, 在log和通知里提示给用户.
但定位有时候不准, 也有些在一些机型上, 通知不弹出的问题, 需要进行适配解决.
还可以使用hugo和我自己开发的插桩库, 在相关的Activity和View的头部加注解, 对耗时方法进行排查.
--- done.