16ms原则:Android系统每隔16ms会发出VSYNC信号重绘我们的界面(Activity)。为什么是16ms, 因为Android设定的刷新率是60FPS(Frame Per Second), 也就是每秒60帧的刷新率, 约合16ms刷新一次。
卡顿:从用户角度说,App操作起来缓慢,响应不及时,列表滑动一顿一顿的,动画刷新不流畅等等一些直观感受。从系统角度来说,屏幕刷新的帧率不稳定,无法保证每秒绘制60帧,也就是说有掉帧的情况发生。
UI卡顿的原理:Android每16ms就会绘制一次Activity,通过上述的结论我们知道,如果由于一些原因导致了我们的逻辑、CPU耗时、GPU耗时大于16ms,UI就无法完成一次绘制,那么就会造成卡顿。
常见卡顿原因及解决方案:
一、过度绘制
去除不必要的背景色:
(1) 设置窗口背景色为通用背景色,去除根布局背景色
(2) 若页面背景色与通用背景色不一致,在页面渲染完成后移除窗口背景色
(3) 去除和列表背景色相同的Item背景色
布局视图树扁平化:
(1) 移除嵌套布局
(2) 使用merge、include标签
(3) 使用性能消耗更小布局(ConstraintLayout)
减少透明色,即alpha属性的使用:
(1) 通过使用半透明颜色值(#77000000)代替
二、UI 线程的复杂运算
UI线程的复杂运算会造成UI无响应, 当然更多的是造成UI响应停滞, 卡顿。产生ANR已经是卡顿的极致了
解决方案:运算阻塞导致的卡顿的分析, 可以使用 Traceview 这个工具。
三、频繁的 GC
频繁GC的原因:(1) 内存抖动(Memory Churn), 即大量的对象被创建又在短时间内马上被释放。(2) 瞬间产生大量的对象会严重占用 Young Generation 的内存区域, 当达到阀值, 剩余空间不够的时候, 也会触发 GC。即使每次分配的对象需要占用很少的内存,但是叠加在一起会增加 Heap 的压力, 从而触发更多的 GC。
解决方案:瞬间大量产生对象一般是因为我们在代码的循环中 new 对象, 或是在 onDraw 中创建对象等, 尽量不要在循环中大量的使用局部变量。
过度绘制检测
在Android手机的"系统设置"-->"开发者选项"-->"调试GPU过度绘制"-->"显示GPU过度绘制"中开启调试。
蓝色,淡绿,淡红,深红代表了4种不同程度的过度绘制(Overdraw)情况。
蓝色: 意味着overdraw 1倍,像素绘制了两次。大片的蓝色还是可以接受的(若整个窗口是蓝色的,可以摆脱一层)。
绿色: 意味着overdraw 2倍,像素绘制了三次。中等大小的绿色区域是可以接受的,你应该尝试优化、减少它们。
淡红: 意味着overdraw 3倍,像素绘制了四次,小范围可以接受。
深红: 意味着overdraw 4倍,像素绘制了五次或者更多。这是不可接受的,要修复它们。
我们的目标就是尽量减少红色 Overdraw,最理想的是蓝色,一个像素只绘制一次,合格的页面绘制是白色、蓝色为主,绿色以上区域不能超过整个的三分之一,颜色越浅越好。
解决方案:见文章的常见卡顿原因及解决方案
分析工具有
分析工具1:Android systrace
分析工具1:Method Profiling
还是打开DDMS,选中你的应用,点击第六个图标,
这边默认OK
点击OK开始抓取,接着滑动手机复现卡顿现象。最后再次点击第六个钮即可。
这里只看上图中的main就可以了。
点击main方法后会展开它的父方法(即调用main的方法)和它的子方法(即在main中调用的方法)。这里一般点击后面百分数较大的那个子方法(百分数表示方法执行所占用的cpu时间)。
接着要做的就是一步一步往下点,直到找到我们要找的耗时操作。
最后我们还是来到了这边
上图已经定位了decodeStream方法,再往下走也是进到framework没意义了。剩下的就是怎么将decodeStream放到主线程以外的线程的事情了。
共同学习,写下你的评论
评论加载中...
作者其他优质文章