Android开发|卡顿(你Android UI优化学好了吗?)

卡顿?你Android UI优化学好了吗? 为什么?你的开发的app中会经常遇到程序丶动画卡顿的现象? Android开发|卡顿(你Android UI优化学好了吗?)
文章图片

首先,我们先了解UI优化的解析: 在Android应用开发过程中,屏幕上控件的布局代码和程序的逻辑代码通常是分开的。界面的布局代码是放在一个独立的xml文件中的,这个文件里面是树型组织的,控制着页面的布局。通常,在这个页面中会用到很多控件,控件会用到很多的资源。Android系统本身有很多的资源,包括各种各样的字符串、图片、动画、样式和布局等等,这些都可以在应用程序中直接使用。这样做的好处很多,既可以减少内存的使用,又可以减少部分工作量,也可以缩减程序安装包的大小。
概述: 其实我们在开发好后的app,在使用过程中,经常会看到程序动画卡顿的现象; Android 应用的卡顿,丢帧等,这些影响用户体验的因素绝大部分都与 16ms 这个值有关。我们来讨论下 UI 渲染方面影响应用流畅性的因素。
16ms定义: Android系统每隔16ms会发出VSYNC信号重绘我们的界面(Activity)。为什么是16ms, 因为Android设定的刷新率是60FPS(Frame Per Second), 也就是每秒60帧的刷新率, 约合16ms刷新一次。
UI卡顿的原理:Android每16ms就会绘制一次Activity,通过上述的结论我们知道,如果由于一些原因导致了我们的逻辑、CPU耗时、GPU耗时大于16ms,UI就无法完成一次绘制,那么就会造成卡顿。
卡顿原因与解决方案: 一、过度绘制
1.去除不必要的背景色:

  • 设置窗口背景色为通用背景色,去除根布局背景色
  • 若页面背景色与通用背景色不一致,在页面渲染完成后移除窗口背景色
  • 去除和列表背景色相同的Item背景色
2.布局视图树扁平化:
  • 移除嵌套布局
  • 使用merge、include标签
  • 使用性能消耗更小布局(ConstraintLayout)
3.减少透明色,即alpha属性的使用:
  • 通过使用半透明颜色值(#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,最理想的是蓝色,一个像素只绘制一次,合格的页面绘制是白色、蓝色为主,绿色以上区域不能超过整个的三分之一,颜色越浅越好。
Android开发|卡顿(你Android UI优化学好了吗?)
文章图片

四丶耗时操作
使用AsyncTask,Thread,HandlerThread,HandlerThread,IntentService等手段将耗时操作移出UI线程。
注意:如果你自己开启线程,你应该调用Process.setThreadPriority()
并传入THREAD_PRIORITY_BACKGROUND
设置线程的priority为"background"。如果不这样做,你开启的线程仍然有可能拖慢你的app,因为默认情况下它与UI线程的优先级相同。
优化思路:
  • 使用成员变量保存引用
  • 使用对象池进行复用
五丶线程过多
显然,这对于app的性能是有负面影响的。线程再多,CPU的资源是有限的,CPU在同一时间能够运行的线程数是不多的,
其他所有的线程都只能等待,同时,每个线程至少需要占用64K的内存。过多的线程只会带来对内存和CPU资源的激烈竞争。
优化思路:建立线程池统一管理
【Android开发|卡顿(你Android UI优化学好了吗?)】总结以上所说:这是常见的一些卡顿现象,以及解决的方案。当然还有可滚动列表丶layout等等一系列现象。更多技术在免费Android技术丶面试题纲丶核心笔记资料。

    推荐阅读