当我们在谈论智能手机屏幕演变时,大部分关注点都放在了形态上,比如各种屏幕切割技术,以及可弯折屏幕在折叠手机上的运用,但很少人会谈论屏幕刷新率的话题。
理论上,屏幕刷新率越高,响应时间越快,自然能实现更流畅的交互和更顺滑的动效,反之则会出现拖影和画面撕裂的现象。这也是为什么,很多主打影音游戏的显示器、游戏本等产品,都会把刷新率当作一个重要指标。
截止到现在,大部分智能手机配备的屏幕仍以 60Hz 为主,但其实也足够使用了,毕竟在小尺寸屏幕下,用户对刷新率的感知并没有那么敏感。
但近些年,也有部分主打游戏的手机在尝试搭载更高刷新率的屏幕,如之前的 Razer Phone,还有华硕的 ROG 游戏手机,它们在默认状态下都是 90Hz 的屏幕刷新率,最高可以达到 120Hz。
此外,苹果也已经在 iPad Pro 中采用了「ProMotion」屏幕技术,它会自动根据屏幕显示内容来调整刷新率。比如看电影时可能只有 48Hz,但切换到用 Apple Pencil 书写或是玩游戏状态下,则会自动提高到 120Hz。
当然,脱离软件支持讨论屏幕刷新率其实意义不大,如果你玩的手机游戏最高只支持 30fps,那么就算屏幕刷新率能跑到 120Hz,肉眼看到优势也并不明显。
————专业理论分割线—————
一、什么是卡顿
APP使用起来卡顿,主要是用户在使用APP时的感知,主要表现在APP页面的刷新,滑动时的流畅度。例如用户在某个页面滑动时有明显卡住的现象就是卡顿了。开发中有一个16ms原则,即你的APP在16ms内没有更新完界面,用户就会有卡顿的感受。
二、哪些原因造成卡顿
1.UI造成的卡顿
- 过于复杂的布局
- 过度绘制
- 动画
2. 主线程执行了耗时操作
3. 频繁的GC
三、怎么优化卡顿?
1.UI卡顿优化
- 布局优化
- 相同层级可实现的页面使用LineraLayout代替RelativeLayout,因为从源码中我们可以知道,LineraLayout在没有设置 weight属性的时候onMeasure()只执行一次,而RelativeLayout都要执行两次。
- 复杂层级的布局可使用ConstraintLayout来减少层级,ConstraintLayout是一个非常强大的布局控件,很多相对复杂的布局都可以使用ConstraintLayout一个层级就可以实现功能。
- 使用merge标签。merge和include结合使用,可以减少布局层级,例如一个include的布局文件中:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
这里我们可以使用merge来代替LinearLayout,这样就等于减少了LinearLayout这一个层级。
- 使用 ViewStub标签:ViewStub,是一个大小为0 ,默认不可见的控件,只有给他设置成了View.Visible或调用了它的inflate()之后才会填充布局资源,也就是说占用资源少。所以当我们有一些布局是在特定条件下才需要显示时就可以用ViewStub来减少布局的加载,比如我们最常用的空白页(即网络异常时的错误提示页面)。
- 使用工具 Hierarchy Viewer来分析布局,查找可优化的地方。
2. 过度绘制优化
- 使用overdraw检测, 设置 -> 开发者选项 -> 调试GPU过度绘制 -> 显示GPU过度绘制,通过不同颜色来发现哪些地方过度绘制。
- 移除不必要的background,比如我们整个页面的背景设置了白色,这样子控件如果再有是白色的就没有必要再设置背景色了。
- 对于自定义的view要减少重复计算和绘制。
3. 动画优化
- 有些酷炫的动画往往对性能要求比较高,所以可以采用分级方式,判断手机类型,低端手机减少动画。
2.主线程耗时操作操作优化
- 主线程也叫UI线程主要的任务是处理用户交互、绘制界面、显示数据、消息处理等工作,如果耗时操作如请求网络数据、操作数据库、读取文件等就不能放在主线程来,可以开启子线程来操作。
- 使用线程池来代替单独创建子线程,因为频繁的创建和销毁线程很耗时,创建太多的子线程也会抢占主线程的CPU使用,从而导致卡顿。
3.频繁的GC优化
- 需要频繁操作字符串时使用 StringBuilder 。
- new对象的时候要注意,尽量不要在需要频繁执行的地方New对象。
— — — — — — — —